From 6f584464b6c2314eb5cddce267c49a5414829ab0 Mon Sep 17 00:00:00 2001 From: JohnnyCena123 Date: Wed, 8 Oct 2025 16:04:29 +0300 Subject: [PATCH 001/102] remove duplicate entry from `keyMappingRGFW` (#5242) --- src/platforms/rcore_desktop_rgfw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index f2e2a7407..8c4deeb9a 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -135,7 +135,6 @@ static bool RGFW_disableCursor = false; static const unsigned short keyMappingRGFW[] = { [RGFW_keyNULL] = KEY_NULL, [RGFW_return] = KEY_ENTER, - [RGFW_return] = KEY_ENTER, [RGFW_apostrophe] = KEY_APOSTROPHE, [RGFW_comma] = KEY_COMMA, [RGFW_minus] = KEY_MINUS, From f62565dc726df092e8c136a924f3ecf9abf8b4d9 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 8 Oct 2025 18:16:46 +0200 Subject: [PATCH 002/102] Update text_unicode_ranges.c --- examples/text/text_unicode_ranges.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/text/text_unicode_ranges.c b/examples/text/text_unicode_ranges.c index 473bee64f..2ed25e72f 100644 --- a/examples/text/text_unicode_ranges.c +++ b/examples/text/text_unicode_ranges.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 5.5, last time updated with raylib 5.6 * -* Example contributed by Vlad Adrian (@demizdor) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Vadim Gunko (@GuvaCode) 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) 2025 Vlad Adrian (@demizdor) and Ramon Santamaria (@raysan5) +* Copyright (c) 2025 Vadim Gunko (@GuvaCode) and Ramon Santamaria (@raysan5) * ********************************************************************************************/ From 04a1a0293e886f396ac89118e3e14979123d727f Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 8 Oct 2025 18:17:32 +0200 Subject: [PATCH 003/102] Update examples_list.txt --- examples/examples_list.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/examples_list.txt b/examples/examples_list.txt index c6f2a97b3..81a61fb97 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -108,7 +108,7 @@ text;text_input_box;★★☆☆;1.7;3.5;2017;2025;"Ramon Santamaria";@raysan5 text;text_writing_anim;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 text;text_rectangle_bounds;★★★★;2.5;4.0;2018;2025;"Vlad Adrian";@demizdor text;text_unicode_emojis;★★★★;2.5;4.0;2019;2025;"Vlad Adrian";@demizdor -text;text_unicode_ranges;★★★★;5.5;5.6;2025;2025;"Vlad Adrian";@demizdor +text;text_unicode_ranges;★★★★;5.5;5.6;2025;2025;"Vadim Gunko";@GuvaCode text;text_3d_drawing;★★★★;3.5;4.0;2021;2025;"Vlad Adrian";@demizdor text;text_codepoints_loading;★★★☆;4.2;4.2;2022;2025;"Ramon Santamaria";@raysan5 text;text_inline_styling;★★★☆;5.6-dev;5.6-dev;2025;2025;"Wagner Barongello";@SultansOfCode From 767df4cf526b78a64393a790d252bea21b71627c Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Oct 2025 01:09:55 +0200 Subject: [PATCH 004/102] Update core_render_texture.c --- examples/core/core_render_texture.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/core/core_render_texture.c b/examples/core/core_render_texture.c index a48982b3d..974d6f350 100644 --- a/examples/core/core_render_texture.c +++ b/examples/core/core_render_texture.c @@ -65,6 +65,7 @@ int main(void) ClearBackground(SKYBLUE); + DrawRectangle(0, 0, 20, 20, RED); DrawCircleV(ballPosition, (float)ballRadius, MAROON); EndTextureMode(); @@ -75,11 +76,12 @@ int main(void) ClearBackground(RAYWHITE); // Draw our render texture with rotation applied - // NOTE: We set the origin of the texture to the center of the render texture + // NOTE 1: We set the origin of the texture to the center of the render texture + // NOTE 2: We flip vertically the texture setting negative source rectangle height DrawTexturePro(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, - (Rectangle){ screenWidth/2, screenHeight/2, target.texture.width, -target.texture.height }, (Vector2){ target.texture.width/2, target.texture.height/2 }, rotation, WHITE); + (Rectangle){ screenWidth/2, screenHeight/2, target.texture.width, target.texture.height }, DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, BLACK); From 9f831428e6be0eba8762a154e3e9139d4f071970 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 9 Oct 2025 17:16:54 +0200 Subject: [PATCH 005/102] Update core_render_texture.c --- examples/core/core_render_texture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/core/core_render_texture.c b/examples/core/core_render_texture.c index 974d6f350..6b2232f23 100644 --- a/examples/core/core_render_texture.c +++ b/examples/core/core_render_texture.c @@ -80,8 +80,8 @@ int main(void) // NOTE 2: We flip vertically the texture setting negative source rectangle height DrawTexturePro(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, + (Rectangle){ screenWidth/2, screenHeight/2, target.texture.width, target.texture.height }, (Vector2){ target.texture.width/2, target.texture.height/2 }, rotation, WHITE); - (Rectangle){ screenWidth/2, screenHeight/2, target.texture.width, target.texture.height }, DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, BLACK); From 2d7b66dd374eb9d9d1b8bab58318ea8f292d7139 Mon Sep 17 00:00:00 2001 From: Thomas Anderson <5776225+CrackedPixel@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:15:20 -0500 Subject: [PATCH 006/102] change free to RL_FREE (#5265) --- src/rcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index b9098db02..dff2c71a9 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3075,7 +3075,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) hash[4] += e; } - free(msg); + RL_FREE(msg); return hash; } From aaf4c1d3aea4d6dafc33cd7333e251774831982a Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Tue, 14 Oct 2025 15:18:48 -0700 Subject: [PATCH 007/102] always forward declare the windows stuff, prevents failure of rgfw in GCC. (#5269) --- src/rcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rcore.c b/src/rcore.c index dff2c71a9..ccc02ab28 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -161,7 +161,7 @@ #endif // Platform specific defines to handle GetApplicationDirectory() -#if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW)) +#if (defined(_WIN32)) #ifndef MAX_PATH #define MAX_PATH 1025 #endif From e3a562ab57a9fa4a9dbaa3d5ffb67f31c25a4a36 Mon Sep 17 00:00:00 2001 From: Arrangemonk <34814431+Arrangemonk@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:00:24 +0200 Subject: [PATCH 008/102] UpdateModelAnimation does matrixtranspose(matrixinvert) only once per bone instead of per vertex (#5244) --- src/rmodels.c | 79 +++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 1e7599004..f800ad1b1 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -2352,6 +2352,8 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) Mesh mesh = model.meshes[m]; Vector3 animVertex = { 0 }; Vector3 animNormal = { 0 }; + Matrix boneMatrix = { 0 }; + Matrix InverseBoneMatrix = { 0 }; int boneId = 0; int boneCounter = 0; float boneWeight = 0.0; @@ -2359,47 +2361,50 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) const int vValues = mesh.vertexCount*3; // Skip if missing bone data, causes segfault without on some models - if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue; + if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue; - for (int vCounter = 0; vCounter < vValues; vCounter += 3) - { - mesh.animVertices[vCounter] = 0; - mesh.animVertices[vCounter + 1] = 0; - mesh.animVertices[vCounter + 2] = 0; - if (mesh.animNormals != NULL) - { - mesh.animNormals[vCounter] = 0; - mesh.animNormals[vCounter + 1] = 0; - mesh.animNormals[vCounter + 2] = 0; - } + // Iterates over 4 bones per vertex + for (int j = 0; j < 4; j++, boneCounter++) + { + boneWeight = mesh.boneWeights[boneCounter]; + boneId = mesh.boneIds[boneCounter]; - // Iterates over 4 bones per vertex - for (int j = 0; j < 4; j++, boneCounter++) - { - boneWeight = mesh.boneWeights[boneCounter]; - boneId = mesh.boneIds[boneCounter]; + // Early stop when no transformation will be applied + if (boneWeight == 0.0f) continue; - // Early stop when no transformation will be applied - if (boneWeight == 0.0f) continue; - animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; - animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]); - mesh.animVertices[vCounter] += animVertex.x*boneWeight; - mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; - mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; - updated = true; + boneMatrix = model.meshes[m].boneMatrices[boneId]; + InverseBoneMatrix = MatrixTranspose(MatrixInvert(boneMatrix)); - // Normals processing - // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) - if ((mesh.normals != NULL) && (mesh.animNormals != NULL )) - { - animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; - animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model.meshes[m].boneMatrices[boneId]))); - mesh.animNormals[vCounter] += animNormal.x*boneWeight; - mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; - mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; - } - } - } + for (int vCounter = 0; vCounter < vValues; vCounter += 3) + { + mesh.animVertices[vCounter] = 0; + mesh.animVertices[vCounter + 1] = 0; + mesh.animVertices[vCounter + 2] = 0; + if (mesh.animNormals != NULL) + { + mesh.animNormals[vCounter] = 0; + mesh.animNormals[vCounter + 1] = 0; + mesh.animNormals[vCounter + 2] = 0; + } + animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; + animVertex = Vector3Transform(animVertex, boneMatrix); + mesh.animVertices[vCounter] += animVertex.x*boneWeight; + mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; + mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; + updated = true; + + // Normals processing + // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) + if ((mesh.normals != NULL) && (mesh.animNormals != NULL)) + { + animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; + animNormal = Vector3Transform(animNormal, InverseBoneMatrix); + mesh.animNormals[vCounter] += animNormal.x*boneWeight; + mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; + mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; + } + } + } if (updated) { From 7191749d66aca458ac5d8cc0401c2c87331b367a Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Wed, 15 Oct 2025 10:02:52 -0700 Subject: [PATCH 009/102] [examples] Fix examples to work in MSVC (#5267) * Fix warnings in many examples Add examples to MSVC solution correctly * fix CI error --------- Co-authored-by: Ray --- examples/audio/audio_sound_positioning.c | 2 +- examples/core/core_3d_camera_fps.c | 8 +- examples/core/core_input_gestures_testbed.c | 66 +- examples/core/core_monitor_change.c | 15 +- examples/core/core_render_texture.c | 6 +- examples/core/core_undo_redo.c | 62 +- examples/models/models_basic_voxel.c | 4 +- .../models/models_geometry_textures_cube.c | 2 +- examples/models/models_tesseract_view.c | 2 +- examples/others/rlgl_compute_shader.c | 2 +- examples/shaders/shaders_basic_pbr.c | 6 +- examples/shaders/shaders_lightmap_rendering.c | 8 +- .../shaders/shaders_normalmap_rendering.c | 2 +- examples/shapes/shapes_bullet_hell.c | 12 +- examples/shapes/shapes_dashed_line.c | 2 +- examples/shapes/shapes_digital_clock.c | 22 +- examples/shapes/shapes_double_pendulum.c | 24 +- examples/shapes/shapes_recursive_tree.c | 4 +- examples/shapes/shapes_vector_angle.c | 12 +- examples/text/text_inline_styling.c | 8 +- examples/text/text_unicode_ranges.c | 6 +- examples/textures/textures_image_channel.c | 10 +- .../VS2022/examples/core_delta_time.vcxproj | 2 +- .../examples/core_monitor_change.vcxproj | 2 +- .../models_geometry_textures_cube.vcxproj | 2 +- .../examples/shaders_ascii_rendering.vcxproj | 2 +- .../examples/shapes_dashed_line.vcxproj | 2 +- .../examples/shapes_digital_clock.vcxproj | 16 +- .../examples/shapes_kaleidoscope.vcxproj | 2 +- .../examples/shapes_recursive_tree.vcxproj | 569 ++++++++++++++++++ .../examples/shapes_triangle_strip.vcxproj | 569 ++++++++++++++++++ .../VS2022/examples/web_basic_window.vcxproj | 2 +- projects/VS2022/raylib.sln | 496 +++++++-------- src/rcore.c | 6 +- 34 files changed, 1550 insertions(+), 405 deletions(-) create mode 100644 projects/VS2022/examples/shapes_recursive_tree.vcxproj create mode 100644 projects/VS2022/examples/shapes_triangle_strip.vcxproj diff --git a/examples/audio/audio_sound_positioning.c b/examples/audio/audio_sound_positioning.c index 69756fa23..4d29954f6 100644 --- a/examples/audio/audio_sound_positioning.c +++ b/examples/audio/audio_sound_positioning.c @@ -60,7 +60,7 @@ int main(void) //---------------------------------------------------------------------------------- UpdateCamera(&camera, CAMERA_FREE); - float th = GetTime(); + float th = (float)GetTime(); Vector3 spherePos = { .x = 5.0f*cosf(th), diff --git a/examples/core/core_3d_camera_fps.c b/examples/core/core_3d_camera_fps.c index c3c779431..7aa79c174 100644 --- a/examples/core/core_3d_camera_fps.c +++ b/examples/core/core_3d_camera_fps.c @@ -198,8 +198,8 @@ void UpdateBody(Body *body, float rot, char side, char forward, bool jumpPressed //PlaySound(fxJump); } - Vector3 front = (Vector3){ sin(rot), 0.f, cos(rot) }; - Vector3 right = (Vector3){ cos(-rot), 0.f, sin(-rot) }; + Vector3 front = (Vector3){ sinf(rot), 0.f, cosf(rot) }; + Vector3 right = (Vector3){ cosf(-rot), 0.f, sinf(-rot) }; Vector3 desiredDir = (Vector3){ input.x*right.x + input.y*front.x, 0.0f, input.x*right.z + input.y*front.z, }; body->dir = Vector3Lerp(body->dir, desiredDir, CONTROL*delta); @@ -267,8 +267,8 @@ static void UpdateCameraFPS(Camera *camera) // Head animation // Rotate up direction around forward axis - float headSin = sin(headTimer*PI); - float headCos = cos(headTimer*PI); + float headSin = sinf(headTimer*PI); + float headCos = cosf(headTimer*PI); const float stepRotation = 0.01f; camera->up = Vector3RotateByAxisAngle(up, pitch, headSin*stepRotation + lean.x); diff --git a/examples/core/core_input_gestures_testbed.c b/examples/core/core_input_gestures_testbed.c index 055240801..dc47136c2 100644 --- a/examples/core/core_input_gestures_testbed.c +++ b/examples/core/core_input_gestures_testbed.c @@ -177,33 +177,33 @@ int main(void) ClearBackground(RAYWHITE); // Draw common elements - DrawText("*", messagePosition.x + 5, messagePosition.y + 5, 10, BLACK); - DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", messagePosition.x + 15, messagePosition.y + 5, 10, BLACK); - DrawText("*", messagePosition.x + 5, messagePosition.y + 35, 10, BLACK); - DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.", messagePosition.x + 15, messagePosition.y + 35, 10, BLACK); + DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 5, 10, BLACK); + DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", (int)messagePosition.x + 15, (int)messagePosition.y + 5, 10, BLACK); + DrawText("*", (int)messagePosition.x + 5, (int)messagePosition.y + 35, 10, BLACK); + DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.", (int)messagePosition.x + 15, (int)messagePosition.y + 35, 10, BLACK); // Draw last gesture - DrawText("Last gesture", lastGesturePosition.x + 33, lastGesturePosition.y - 47, 20, BLACK); - DrawText("Swipe Tap Pinch Touch", lastGesturePosition.x + 17, lastGesturePosition.y - 18, 10, BLACK); - DrawRectangle(lastGesturePosition.x + 20, lastGesturePosition.y, 20, 20, lastGesture == GESTURE_SWIPE_UP ? RED : LIGHTGRAY); - DrawRectangle(lastGesturePosition.x, lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_LEFT ? RED : LIGHTGRAY); - DrawRectangle(lastGesturePosition.x + 40, lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_RIGHT ? RED : LIGHTGRAY); - DrawRectangle(lastGesturePosition.x + 20, lastGesturePosition.y + 40, 20, 20, lastGesture == GESTURE_SWIPE_DOWN ? RED : LIGHTGRAY); - DrawCircle(lastGesturePosition.x + 80, lastGesturePosition.y + 16, 10, lastGesture == GESTURE_TAP ? BLUE : LIGHTGRAY); + DrawText("Last gesture", (int)lastGesturePosition.x + 33, (int)lastGesturePosition.y - 47, 20, BLACK); + DrawText("Swipe Tap Pinch Touch", (int)lastGesturePosition.x + 17, (int)lastGesturePosition.y - 18, 10, BLACK); + DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y, 20, 20, lastGesture == GESTURE_SWIPE_UP ? RED : LIGHTGRAY); + DrawRectangle((int)lastGesturePosition.x, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_LEFT ? RED : LIGHTGRAY); + DrawRectangle((int)lastGesturePosition.x + 40, (int)lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_RIGHT ? RED : LIGHTGRAY); + DrawRectangle((int)lastGesturePosition.x + 20, (int)lastGesturePosition.y + 40, 20, 20, lastGesture == GESTURE_SWIPE_DOWN ? RED : LIGHTGRAY); + DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 16, 10, lastGesture == GESTURE_TAP ? BLUE : LIGHTGRAY); DrawRing( (Vector2){lastGesturePosition.x + 103, lastGesturePosition.y + 16}, 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == GESTURE_DRAG ? LIME : LIGHTGRAY); - DrawCircle(lastGesturePosition.x + 80, lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY); - DrawCircle(lastGesturePosition.x + 103, lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY); - DrawTriangle((Vector2){ lastGesturePosition.x + 122, lastGesturePosition.y + 16 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 6 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY); + DrawCircle((int)lastGesturePosition.x + 80, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY); + DrawCircle((int)lastGesturePosition.x + 103, (int)lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY); + DrawTriangle((Vector2){ lastGesturePosition.x + 122, lastGesturePosition.y + 16 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 26 }, (Vector2){lastGesturePosition.x + 137, lastGesturePosition.y + 6 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY); DrawTriangle((Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 6 }, (Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 162, lastGesturePosition.y + 16 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY); DrawTriangle((Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 33 }, (Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 140, lastGesturePosition.y + 43 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY); DrawTriangle((Vector2){ lastGesturePosition.x + 144, lastGesturePosition.y + 43 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 33 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY); - for (i = 0; i < 4; i++) DrawCircle(lastGesturePosition.x + 180, lastGesturePosition.y + 7 + i*15, 5, touchCount <= i? LIGHTGRAY : gestureColor); + for (i = 0; i < 4; i++) DrawCircle((int)lastGesturePosition.x + 180, (int)lastGesturePosition.y + 7 + i*15, 5, touchCount <= i? LIGHTGRAY : gestureColor); // Draw gesture log - DrawText("Log", gestureLogPosition.x, gestureLogPosition.y, 20, BLACK); + DrawText("Log", (int)gestureLogPosition.x, (int)gestureLogPosition.y, 20, BLACK); // Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle) - for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE) DrawText(gestureLog[ii], gestureLogPosition.x, gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY)); + for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE) DrawText(gestureLog[ii], (int)gestureLogPosition.x, (int)gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY)); Color logButton1Color, logButton2Color; switch (logMode) { @@ -213,31 +213,31 @@ int main(void) default: logButton1Color=GRAY; logButton2Color=GRAY; break; } DrawRectangleRec(logButton1, logButton1Color); - DrawText("Hide", logButton1.x + 7, logButton1.y + 3, 10, WHITE); - DrawText("Repeat", logButton1.x + 7, logButton1.y + 13, 10, WHITE); + DrawText("Hide", (int)logButton1.x + 7, (int)logButton1.y + 3, 10, WHITE); + DrawText("Repeat", (int)logButton1.x + 7, (int)logButton1.y + 13, 10, WHITE); DrawRectangleRec(logButton2, logButton2Color); - DrawText("Hide", logButton1.x + 62, logButton1.y + 3, 10, WHITE); - DrawText("Hold", logButton1.x + 62, logButton1.y + 13, 10, WHITE); + DrawText("Hide", (int)logButton1.x + 62, (int)logButton1.y + 3, 10, WHITE); + DrawText("Hold", (int)logButton1.x + 62, (int)logButton1.y + 13, 10, WHITE); // Draw protractor - DrawText("Angle", protractorPosition.x + 55, protractorPosition.y + 76, 10, BLACK); + DrawText("Angle", (int)protractorPosition.x + 55, (int)protractorPosition.y + 76, 10, BLACK); const char *angleString = TextFormat("%f", currentAngleDegrees); const int angleStringDot = TextFindIndex(angleString, "."); const char *angleStringTrim = TextSubtext(angleString, 0, angleStringDot + 3); - DrawText( angleStringTrim, protractorPosition.x + 55, protractorPosition.y + 92, 20, gestureColor); - DrawCircle(protractorPosition.x, protractorPosition.y, 80.0f, WHITE); + DrawText( angleStringTrim, (int)protractorPosition.x + 55, (int)protractorPosition.y + 92, 20, gestureColor); + DrawCircleV(protractorPosition, 80.0f, WHITE); DrawLineEx((Vector2){ protractorPosition.x - 90, protractorPosition.y }, (Vector2){ protractorPosition.x + 90, protractorPosition.y }, 3.0f, LIGHTGRAY); DrawLineEx((Vector2){ protractorPosition.x, protractorPosition.y - 90 }, (Vector2){ protractorPosition.x, protractorPosition.y + 90 }, 3.0f, LIGHTGRAY); DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y - 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y + 45 }, 3.0f, GREEN); DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y + 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y - 45 }, 3.0f, GREEN); - DrawText("0", protractorPosition.x + 96, protractorPosition.y - 9, 20, BLACK); - DrawText("30", protractorPosition.x + 74, protractorPosition.y - 68, 20, BLACK); - DrawText("90", protractorPosition.x - 11, protractorPosition.y - 110, 20, BLACK); - DrawText("150", protractorPosition.x - 100, protractorPosition.y - 68, 20, BLACK); - DrawText("180", protractorPosition.x - 124, protractorPosition.y - 9, 20, BLACK); - DrawText("210", protractorPosition.x - 100, protractorPosition.y + 50, 20, BLACK); - DrawText("270", protractorPosition.x - 18, protractorPosition.y + 92, 20, BLACK); - DrawText("330", protractorPosition.x + 72, protractorPosition.y + 50, 20, BLACK); + DrawText("0", (int)protractorPosition.x + 96, (int)protractorPosition.y - 9, 20, BLACK); + DrawText("30", (int)protractorPosition.x + 74, (int)protractorPosition.y - 68, 20, BLACK); + DrawText("90", (int)protractorPosition.x - 11, (int)protractorPosition.y - 110, 20, BLACK); + DrawText("150", (int)protractorPosition.x - 100, (int)protractorPosition.y - 68, 20, BLACK); + DrawText("180", (int)protractorPosition.x - 124, (int)protractorPosition.y - 9, 20, BLACK); + DrawText("210", (int)protractorPosition.x - 100, (int)protractorPosition.y + 50, 20, BLACK); + DrawText("270", (int)protractorPosition.x - 18, (int)protractorPosition.y + 92, 20, BLACK); + DrawText("330", (int)protractorPosition.x + 72, (int)protractorPosition.y + 50, 20, BLACK); if (currentAngleDegrees != 0.0f) DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor); // Draw touch and mouse pointer points @@ -251,7 +251,7 @@ int main(void) DrawCircleV(touchPosition[i], 5.0f, gestureColor); } - if (touchCount == 2) DrawLineEx(touchPosition[0], touchPosition[1], ((currentGesture == 512)? 8 : 12), gestureColor); + if (touchCount == 2) DrawLineEx(touchPosition[0], touchPosition[1], ((currentGesture == 512)? 8.0f : 12.0f), gestureColor); } else { diff --git a/examples/core/core_monitor_change.c b/examples/core/core_monitor_change.c index c85b3f633..3286ba22d 100644 --- a/examples/core/core_monitor_change.c +++ b/examples/core/core_monitor_change.c @@ -22,7 +22,7 @@ // Monitor Details typedef struct Monitor { Vector2 position; - char *name; + const char *name; int width; int height; int physicalWidth; @@ -76,10 +76,10 @@ int main(void) GetMonitorPhysicalHeight(i), GetMonitorRefreshRate(i) }; - if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = monitors[i].position.x*-1; + if (monitors[i].position.x < monitorOffsetX) monitorOffsetX = (int)monitors[i].position.x*-1; - const int width = monitors[i].position.x + monitors[i].width; - const int height = monitors[i].position.y + monitors[i].height; + const int width = (int)monitors[i].position.x + monitors[i].width; + const int height = (int)monitors[i].position.y + monitors[i].height; if (maxWidth < width) maxWidth = width; if (maxHeight < height) maxHeight = height; @@ -99,9 +99,8 @@ int main(void) // Get currentMonitorIndex if manually moved currentMonitorIndex = GetCurrentMonitor(); } - const Monitor currentMonitor = monitors[currentMonitorIndex]; - float monitorScale = 0.6; + float monitorScale = 0.6f; if(maxHeight > maxWidth + monitorOffsetX) monitorScale *= ((float)screenHeight/(float)maxHeight); else monitorScale *= ((float)screenWidth/(float)(maxWidth + monitorOffsetX)); @@ -128,7 +127,7 @@ int main(void) }; // Draw monitor name and information inside the rectangle - DrawText(TextFormat("[%i] %s", i, monitors[i].name), rec.x + 10, rec.y + (int)(100*monitorScale), (int)(120*monitorScale), BLUE); + DrawText(TextFormat("[%i] %s", i, monitors[i].name), (int)rec.x + 10, (int)rec.y + (int)(100*monitorScale), (int)(120*monitorScale), BLUE); DrawText( TextFormat("Resolution: [%ipx x %ipx]\nRefreshRate: [%ihz]\nPhysical Size: [%imm x %imm]\nPosition: %3.0f x %3.0f", monitors[i].width, @@ -138,7 +137,7 @@ int main(void) monitors[i].physicalHeight, monitors[i].position.x, monitors[i].position.y - ), rec.x + 10, rec.y + (int)(200*monitorScale), (int)(120*monitorScale), DARKGRAY); + ), (int)rec.x + 10, (int)rec.y + (int)(200*monitorScale), (int)(120*monitorScale), DARKGRAY); // Highlight current monitor if (i == currentMonitorIndex) diff --git a/examples/core/core_render_texture.c b/examples/core/core_render_texture.c index 6b2232f23..47dc66e0f 100644 --- a/examples/core/core_render_texture.c +++ b/examples/core/core_render_texture.c @@ -79,9 +79,9 @@ int main(void) // NOTE 1: We set the origin of the texture to the center of the render texture // NOTE 2: We flip vertically the texture setting negative source rectangle height DrawTexturePro(target.texture, - (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, - (Rectangle){ screenWidth/2, screenHeight/2, target.texture.width, target.texture.height }, - (Vector2){ target.texture.width/2, target.texture.height/2 }, rotation, WHITE); + (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, + (Rectangle){ screenWidth/2.0f, screenHeight/2.0f, (float)target.texture.width, (float)target.texture.height }, + (Vector2){ target.texture.width/2.0f, target.texture.height/2.0f }, rotation, WHITE); DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, BLACK); diff --git a/examples/core/core_undo_redo.c b/examples/core/core_undo_redo.c index 874f68800..45b19e10f 100644 --- a/examples/core/core_undo_redo.c +++ b/examples/core/core_undo_redo.c @@ -187,42 +187,42 @@ int main(void) if (lastUndoIndex > firstUndoIndex) { for (int i = firstUndoIndex; i < currentUndoIndex; i++) - DrawRectangle(gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, - GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY); + DrawRectangleRec((Rectangle){gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, + GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); } else if (firstUndoIndex > lastUndoIndex) { if ((currentUndoIndex < MAX_UNDO_STATES) && (currentUndoIndex > lastUndoIndex)) { for (int i = firstUndoIndex; i < currentUndoIndex; i++) - DrawRectangle(gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, - GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY); + DrawRectangleRec((Rectangle) { gridPosition.x + states[i].cell.x * GRID_CELL_SIZE, gridPosition.y + states[i].cell.y * GRID_CELL_SIZE, + GRID_CELL_SIZE, GRID_CELL_SIZE }, LIGHTGRAY); } else { for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++) - DrawRectangle(gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, + DrawRectangle((int)gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, (int)gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY); for (int i = 0; i < currentUndoIndex; i++) - DrawRectangle(gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, + DrawRectangle((int)gridPosition.x + states[i].cell.x*GRID_CELL_SIZE, (int)gridPosition.y + states[i].cell.y*GRID_CELL_SIZE, GRID_CELL_SIZE, GRID_CELL_SIZE, LIGHTGRAY); } } // Draw game grid for (int y = 0; y <= MAX_GRID_CELLS_Y; y++) - DrawLine(gridPosition.x, gridPosition.y + y*GRID_CELL_SIZE, - gridPosition.x + MAX_GRID_CELLS_X*GRID_CELL_SIZE, gridPosition.y + y*GRID_CELL_SIZE, GRAY); + DrawLine((int)gridPosition.x, (int)gridPosition.y + y*GRID_CELL_SIZE, + (int)gridPosition.x + MAX_GRID_CELLS_X*GRID_CELL_SIZE, (int)gridPosition.y + y*GRID_CELL_SIZE, GRAY); for (int x = 0; x <= MAX_GRID_CELLS_X; x++) - DrawLine(gridPosition.x + x*GRID_CELL_SIZE, gridPosition.y, - gridPosition.x + x*GRID_CELL_SIZE, gridPosition.y + MAX_GRID_CELLS_Y*GRID_CELL_SIZE, GRAY); + DrawLine((int)gridPosition.x + x*GRID_CELL_SIZE, (int)gridPosition.y, + (int)gridPosition.x + x*GRID_CELL_SIZE, (int)gridPosition.y + MAX_GRID_CELLS_Y*GRID_CELL_SIZE, GRAY); // Draw player - DrawRectangle(gridPosition.x + player.cell.x*GRID_CELL_SIZE, gridPosition.y + player.cell.y*GRID_CELL_SIZE, + DrawRectangle((int)gridPosition.x + player.cell.x*GRID_CELL_SIZE, (int)gridPosition.y + player.cell.y*GRID_CELL_SIZE, GRID_CELL_SIZE + 1, GRID_CELL_SIZE + 1, player.color); // Draw undo system buffer info - DrawText("UNDO STATES:", undoInfoPos.x - 85, undoInfoPos.y + 9, 10, DARKGRAY); + DrawText("UNDO STATES:", (int)undoInfoPos.x - 85, (int)undoInfoPos.y + 9, 10, DARKGRAY); DrawUndoBuffer(undoInfoPos, firstUndoIndex, lastUndoIndex, currentUndoIndex, 24); EndDrawing(); @@ -247,15 +247,15 @@ int main(void) static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoIndex, int currentUndoIndex, int slotSize) { // Draw index marks - DrawRectangle(position.x + 8 + slotSize*currentUndoIndex, position.y - 10, 8, 8, RED); - DrawRectangleLines(position.x + 2 + slotSize*firstUndoIndex, position.y + 27, 8, 8, BLACK); - DrawRectangle(position.x + 14 + slotSize*lastUndoIndex, position.y + 27, 8, 8, BLACK); + DrawRectangle((int)position.x + 8 + slotSize*currentUndoIndex, (int)position.y - 10, 8, 8, RED); + DrawRectangleLines((int)position.x + 2 + slotSize*firstUndoIndex, (int)position.y + 27, 8, 8, BLACK); + DrawRectangle((int)position.x + 14 + slotSize*lastUndoIndex, (int)position.y + 27, 8, 8, BLACK); // Draw background gray slots for (int i = 0; i < MAX_UNDO_STATES; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, LIGHTGRAY); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, GRAY); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIGHTGRAY); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GRAY); } // Draw occupied slots: firstUndoIndex --> lastUndoIndex @@ -263,22 +263,22 @@ static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoInd { for (int i = firstUndoIndex; i < lastUndoIndex + 1; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, SKYBLUE); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, BLUE); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE); } } else if (lastUndoIndex < firstUndoIndex) { for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, SKYBLUE); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, BLUE); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE); } for (int i = 0; i < lastUndoIndex + 1; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, SKYBLUE); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, BLUE); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, SKYBLUE); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, BLUE); } } @@ -287,26 +287,26 @@ static void DrawUndoBuffer(Vector2 position, int firstUndoIndex, int lastUndoInd { for (int i = firstUndoIndex; i < currentUndoIndex; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, GREEN); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, LIME); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME); } } else if (currentUndoIndex < firstUndoIndex) { for (int i = firstUndoIndex; i < MAX_UNDO_STATES; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, GREEN); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, LIME); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME); } for (int i = 0; i < currentUndoIndex; i++) { - DrawRectangle(position.x + slotSize*i, position.y, slotSize, slotSize, GREEN); - DrawRectangleLines(position.x + slotSize*i, position.y, slotSize, slotSize, LIME); + DrawRectangle((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, GREEN); + DrawRectangleLines((int)position.x + slotSize*i, (int)position.y, slotSize, slotSize, LIME); } } // Draw current selected UNDO slot - DrawRectangle(position.x + slotSize*currentUndoIndex, position.y, slotSize, slotSize, GOLD); - DrawRectangleLines(position.x + slotSize*currentUndoIndex, position.y, slotSize, slotSize, ORANGE); + DrawRectangle((int)position.x + slotSize*currentUndoIndex, (int)position.y, slotSize, slotSize, GOLD); + DrawRectangleLines((int)position.x + slotSize*currentUndoIndex, (int)position.y, slotSize, slotSize, ORANGE); } diff --git a/examples/models/models_basic_voxel.c b/examples/models/models_basic_voxel.c index 8df15d73d..a70da1822 100644 --- a/examples/models/models_basic_voxel.c +++ b/examples/models/models_basic_voxel.c @@ -88,7 +88,7 @@ int main(void) if (!voxels[x][y][z]) continue; // Skip empty voxels // Build a bounding box for this voxel - Vector3 position = { x, y, z }; + Vector3 position = { (float)x, (float)y, (float)z }; BoundingBox box = { (Vector3){ position.x - 0.5f, position.y - 0.5f, position.z - 0.5f }, (Vector3){ position.x + 0.5f, position.y + 0.5f, position.z + 0.5f } @@ -126,7 +126,7 @@ int main(void) { if (!voxels[x][y][z]) continue; - Vector3 position = { x, y, z }; + Vector3 position = { (float)x, (float)y, (float)z }; DrawModel(cubeModel, position, 1.0f, BEIGE); DrawCubeWires(position, 1.0f, 1.0f, 1.0f, BLACK); } diff --git a/examples/models/models_geometry_textures_cube.c b/examples/models/models_geometry_textures_cube.c index f8236f36d..9441c7fd4 100644 --- a/examples/models/models_geometry_textures_cube.c +++ b/examples/models/models_geometry_textures_cube.c @@ -40,7 +40,7 @@ int main(void) // Load image to create texture for the cube Model model = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f)); Image img = LoadImage("resources/cubicmap_atlas.png"); - Image crop = ImageFromImage(img, (Rectangle){0, img.height/2, img.width/2, img.height/2}); + Image crop = ImageFromImage(img, (Rectangle){0, img.height/2.0f, img.width/2.0f, img.height/2.0f}); Texture2D texture = LoadTextureFromImage(crop); UnloadImage(img); UnloadImage(crop); diff --git a/examples/models/models_tesseract_view.c b/examples/models/models_tesseract_view.c index 97a02ca8e..1544873fb 100644 --- a/examples/models/models_tesseract_view.c +++ b/examples/models/models_tesseract_view.c @@ -65,7 +65,7 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - rotation = DEG2RAD*45.0f*GetTime(); + rotation = DEG2RAD*45.0f*(float)GetTime(); for (int i = 0; i < 16; i++) { diff --git a/examples/others/rlgl_compute_shader.c b/examples/others/rlgl_compute_shader.c index 4704b4a7c..14a2b32cd 100644 --- a/examples/others/rlgl_compute_shader.c +++ b/examples/others/rlgl_compute_shader.c @@ -59,7 +59,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [others] example - compute shader"); - const Vector2 resolution = { screenWidth, screenHeight }; + const Vector2 resolution = { (float)screenWidth, (float)screenHeight }; unsigned int brushSize = 8; // Game of Life logic compute shader diff --git a/examples/shaders/shaders_basic_pbr.c b/examples/shaders/shaders_basic_pbr.c index 75dacd5aa..6fb15a607 100644 --- a/examples/shaders/shaders_basic_pbr.c +++ b/examples/shaders/shaders_basic_pbr.c @@ -252,7 +252,11 @@ int main() // Draw spheres to show the lights positions for (int i = 0; i < MAX_LIGHTS; i++) { - Color lightColor = (Color){ lights[i].color[0]*255, lights[i].color[1]*255, lights[i].color[2]*255, lights[i].color[3]*255 }; + Color lightColor = (Color){ + (unsigned char)(lights[i].color[0]*255), + (unsigned char)(lights[i].color[1] * 255), + (unsigned char)(lights[i].color[2] * 255), + (unsigned char)(lights[i].color[3] * 255) }; if (lights[i].enabled) DrawSphereEx(lights[i].position, 0.2f, 8, 8, lightColor); else DrawSphereWires(lights[i].position, 0.2f, 8, 8, ColorAlpha(lightColor, 0.3f)); diff --git a/examples/shaders/shaders_lightmap_rendering.c b/examples/shaders/shaders_lightmap_rendering.c index 232e0901b..e269aada2 100644 --- a/examples/shaders/shaders_lightmap_rendering.c +++ b/examples/shaders/shaders_lightmap_rendering.c @@ -102,7 +102,7 @@ int main(void) BeginBlendMode(BLEND_ADDITIVE); DrawTexturePro( light, - (Rectangle){ 0, 0, light.width, light.height }, + (Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 0, 0, 20, 20 }, (Vector2){ 10.0, 10.0 }, 0.0, @@ -110,7 +110,7 @@ int main(void) ); DrawTexturePro( light, - (Rectangle){ 0, 0, light.width, light.height }, + (Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 8, 4, 20, 20 }, (Vector2){ 10.0, 10.0 }, 0.0, @@ -118,7 +118,7 @@ int main(void) ); DrawTexturePro( light, - (Rectangle){ 0, 0, light.width, light.height }, + (Rectangle){ 0, 0, (float)light.width, (float)light.height }, (Rectangle){ 8, 8, 10, 10 }, (Vector2){ 5.0, 5.0 }, 0.0, @@ -152,7 +152,7 @@ int main(void) DrawTexturePro( lightmap.texture, (Rectangle){ 0, 0, -MAP_SIZE, -MAP_SIZE }, - (Rectangle){ GetRenderWidth() - MAP_SIZE*8 - 10, 10, MAP_SIZE*8, MAP_SIZE*8 }, + (Rectangle){ (float)GetRenderWidth() - MAP_SIZE*8 - 10, 10, (float)MAP_SIZE*8, (float)MAP_SIZE*8 }, (Vector2){ 0.0, 0.0 }, 0.0, WHITE); diff --git a/examples/shaders/shaders_normalmap_rendering.c b/examples/shaders/shaders_normalmap_rendering.c index e66362c07..4859ec813 100644 --- a/examples/shaders/shaders_normalmap_rendering.c +++ b/examples/shaders/shaders_normalmap_rendering.c @@ -113,7 +113,7 @@ int main(void) if (IsKeyPressed(KEY_N)) useNormalMap = !useNormalMap; // Spin plane model at a constant rate - plane.transform = MatrixRotateY(GetTime()*0.5f); + plane.transform = MatrixRotateY((float)GetTime()*0.5f); // Update shader values float lightPos[3] = {lightPosition.x, lightPosition.y, lightPosition.z}; diff --git a/examples/shapes/shapes_bullet_hell.c b/examples/shapes/shapes_bullet_hell.c index 8eaddfbfe..235df4d16 100644 --- a/examples/shapes/shapes_bullet_hell.c +++ b/examples/shapes/shapes_bullet_hell.c @@ -68,8 +68,8 @@ int main(void) // Draw circle to bullet texture, then draw bullet using DrawTexture() // NOTE: This is done to improve the performance, since DrawCircle() is very slow BeginTextureMode(bulletTexture); - DrawCircle(12, 12, bulletRadius, WHITE); - DrawCircleLines(12, 12, bulletRadius, BLACK); + DrawCircle(12, 12, (float)bulletRadius, WHITE); + DrawCircleLines(12, 12, (float)bulletRadius, BLACK); EndTextureMode(); bool drawInPerformanceMode = true; // Switch between DrawCircle() and DrawTexture() @@ -192,8 +192,8 @@ int main(void) if (!bullets[i].disabled) { DrawTexture(bulletTexture.texture, - bullets[i].position.x - bulletTexture.texture.width*0.5f, - bullets[i].position.y - bulletTexture.texture.height*0.5f, + (int)(bullets[i].position.x - bulletTexture.texture.width*0.5f), + (int)(bullets[i].position.y - bulletTexture.texture.height*0.5f), bullets[i].color); } } @@ -206,8 +206,8 @@ int main(void) // Do not draw disabled bullets (out of screen) if (!bullets[i].disabled) { - DrawCircleV(bullets[i].position, bulletRadius, bullets[i].color); - DrawCircleLinesV(bullets[i].position, bulletRadius, BLACK); + DrawCircleV(bullets[i].position, (float)bulletRadius, bullets[i].color); + DrawCircleLinesV(bullets[i].position, (float)bulletRadius, BLACK); } } } diff --git a/examples/shapes/shapes_dashed_line.c b/examples/shapes/shapes_dashed_line.c index 7a6bf3eee..2a11bf64a 100644 --- a/examples/shapes/shapes_dashed_line.c +++ b/examples/shapes/shapes_dashed_line.c @@ -68,7 +68,7 @@ int main(void) ClearBackground(RAYWHITE); // Draw the dashed line with the current properties - DrawLineDashed(lineStartPosition, lineEndPosition, dashLength, blankLength, lineColors[colorIndex]); + DrawLineDashed(lineStartPosition, lineEndPosition, (int)dashLength, (int)blankLength, lineColors[colorIndex]); // Draw UI and Instructions DrawRectangle(5, 5, 265, 95, Fade(SKYBLUE, 0.5f)); diff --git a/examples/shapes/shapes_digital_clock.c b/examples/shapes/shapes_digital_clock.c index 3317202b8..77b020704 100644 --- a/examples/shapes/shapes_digital_clock.c +++ b/examples/shapes/shapes_digital_clock.c @@ -15,6 +15,8 @@ * ********************************************************************************************/ +#define _CRT_SECURE_NO_WARNINGS // Disable some Visual Studio warnings + #include "raylib.h" #include // Required for: cosf(), sinf() @@ -158,7 +160,7 @@ static void UpdateClock(Clock *clock) clock->minute.value = timeinfo->tm_min; clock->hour.value = timeinfo->tm_hour; - clock->hour.angle = (timeinfo->tm_hour%12)*180.0/6.0f; + clock->hour.angle = (timeinfo->tm_hour%12)*180.0f/6.0f; clock->hour.angle += (timeinfo->tm_min%60)*30/60.0f; clock->hour.angle -= 90; @@ -175,8 +177,8 @@ static void UpdateClock(Clock *clock) static void DrawClockAnalog(Clock clock, Vector2 position) { // Draw clock base - DrawCircleV(position, clock.second.length + 40, LIGHTGRAY); - DrawCircleV(position, 12, GRAY); + DrawCircleV(position, clock.second.length + 40.0f, LIGHTGRAY); + DrawCircleV(position, 12.0f, GRAY); // Draw clock minutes/seconds lines for (int i = 0; i < 60; i++) @@ -192,15 +194,15 @@ static void DrawClockAnalog(Clock clock, Vector2 position) } // Draw hand seconds - DrawRectanglePro((Rectangle){ position.x, position.y, clock.second.length, clock.second.thickness }, + DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.second.length, (float)clock.second.thickness }, (Vector2){ 0.0f, clock.second.thickness/2.0f }, clock.second.angle, clock.second.color); // Draw hand minutes - DrawRectanglePro((Rectangle){ position.x, position.y, clock.minute.length, clock.minute.thickness }, + DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.minute.length, (float)clock.minute.thickness }, (Vector2){ 0.0f, clock.minute.thickness/2.0f }, clock.minute.angle, clock.minute.color); // Draw hand hours - DrawRectanglePro((Rectangle){ position.x, position.y, clock.hour.length, clock.hour.thickness }, + DrawRectanglePro((Rectangle){ position.x, position.y, (float)clock.hour.length, (float)clock.hour.thickness }, (Vector2){ 0.0f, clock.hour.thickness/2.0f }, clock.hour.angle, clock.hour.color); } @@ -212,14 +214,14 @@ static void DrawClockDigital(Clock clock, Vector2 position) DrawDisplayValue((Vector2){ position.x, position.y }, clock.hour.value/10, RED, Fade(LIGHTGRAY, 0.3f)); DrawDisplayValue((Vector2){ position.x + 120, position.y }, clock.hour.value%10, RED, Fade(LIGHTGRAY, 0.3f)); - DrawCircle(position.x + 240, position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); - DrawCircle(position.x + 240, position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); + DrawCircle((int)position.x + 240, (int)position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); + DrawCircle((int)position.x + 240, (int)position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); DrawDisplayValue((Vector2){ position.x + 260, position.y }, clock.minute.value/10, RED, Fade(LIGHTGRAY, 0.3f)); DrawDisplayValue((Vector2){ position.x + 380, position.y }, clock.minute.value%10, RED, Fade(LIGHTGRAY, 0.3f)); - DrawCircle(position.x + 500, position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); - DrawCircle(position.x + 500, position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); + DrawCircle((int)position.x + 500, (int)position.y + 70, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); + DrawCircle((int)position.x + 500, (int)position.y + 150, 12, (clock.second.value%2)? RED : Fade(LIGHTGRAY, 0.3f)); DrawDisplayValue((Vector2){ position.x + 520, position.y }, clock.second.value/10, RED, Fade(LIGHTGRAY, 0.3f)); DrawDisplayValue((Vector2){ position.x + 640, position.y }, clock.second.value%10, RED, Fade(LIGHTGRAY, 0.3f)); diff --git a/examples/shapes/shapes_double_pendulum.c b/examples/shapes/shapes_double_pendulum.c index 200f9ad7e..4bcac02f9 100644 --- a/examples/shapes/shapes_double_pendulum.c +++ b/examples/shapes/shapes_double_pendulum.c @@ -21,7 +21,7 @@ // Constant for Simulation #define SIMULATION_STEPS 30 -#define G 9.81 +#define G 9.81f //---------------------------------------------------------------------------------- // Module Functions Declaration @@ -43,9 +43,9 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - double pendulum"); // Simulation Paramters - float l1 = 15, m1 = 0.2, theta1 = DEG2RAD*170, w1 = 0; - float l2 = 15, m2 = 0.1, theta2 = DEG2RAD*0, w2 = 0; - float lengthScaler = 0.1; + float l1 = 15.0f, m1 = 0.2f, theta1 = DEG2RAD*170, w1 = 0; + float l2 = 15.0f, m2 = 0.1f, theta2 = DEG2RAD*0, w2 = 0; + float lengthScaler = 0.1f; float totalM = m1 + m2; Vector2 previousPosition = CalculateDoublePendulumEndPoint(l1, theta1, l2, theta2); @@ -57,8 +57,8 @@ int main(void) float L2 = l2*lengthScaler; // Draw parameters - int lineThick = 20, trailThick = 2; - float fateAlpha = 0.01; + float lineThick = 20, trailThick = 2; + float fateAlpha = 0.01f; // Create framebuffer RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight); @@ -129,15 +129,15 @@ int main(void) ClearBackground(BLACK); // Draw trails texture - DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); + DrawTextureRec(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2){ 0, 0 }, WHITE); // Draw double pendulum - DrawRectanglePro((Rectangle){ screenWidth/2, screenHeight/2 - 100, 10*l1, lineThick }, - (Vector2){0, lineThick*0.5}, 90 - RAD2DEG*theta1, RAYWHITE); + DrawRectanglePro((Rectangle){ screenWidth/2.0f, screenHeight/2.0f - 100, 10*l1, lineThick }, + (Vector2){0, lineThick*0.5f}, 90 - RAD2DEG*theta1, RAYWHITE); Vector2 endpoint1 = CalculatePendulumEndPoint(l1, theta1); - DrawRectanglePro((Rectangle){ screenWidth/2 + endpoint1.x, screenHeight/2 - 100 + endpoint1.y, 10*l2, lineThick }, - (Vector2){0, lineThick*0.5}, 90 - RAD2DEG*theta2, RAYWHITE); + DrawRectanglePro((Rectangle){ screenWidth/2.0f + endpoint1.x, screenHeight/2.0f - 100 + endpoint1.y, 10*l2, lineThick }, + (Vector2){0, lineThick*0.5f}, 90 - RAD2DEG*theta2, RAYWHITE); EndDrawing(); //---------------------------------------------------------------------------------- @@ -159,7 +159,7 @@ int main(void) // Calculate pendulum end point static Vector2 CalculatePendulumEndPoint(float l, float theta) { - return (Vector2){ 10*l*sin(theta), 10*l*cos(theta) }; + return (Vector2){ 10*l*sinf(theta), 10*l*cosf(theta) }; } // Calculate double pendulum end point diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c index 3ec46de4b..7ed02e5c2 100644 --- a/examples/shapes/shapes_recursive_tree.c +++ b/examples/shapes/shapes_recursive_tree.c @@ -48,7 +48,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - shapes recursive tree"); - Vector2 start = { (screenWidth/2.0f) - 125.0f, screenHeight }; + Vector2 start = { (screenWidth/2.0f) - 125.0f, (float)screenHeight }; float angle = 40.0f; float thick = 1.0f; float treeDepth = 10.0f; @@ -66,7 +66,7 @@ int main(void) //---------------------------------------------------------------------------------- float theta = angle*DEG2RAD; - int maxBranches = (int)(powf(2, (int)(treeDepth))); + int maxBranches = (int)(powf(2, floorf(treeDepth))); Branch branches[1024] = { 0 }; int count = 0; diff --git a/examples/shapes/shapes_vector_angle.c b/examples/shapes/shapes_vector_angle.c index 7de296dcb..b5faf4c78 100644 --- a/examples/shapes/shapes_vector_angle.c +++ b/examples/shapes/shapes_vector_angle.c @@ -30,7 +30,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - vector angle"); - Vector2 v0 = { screenWidth/2, screenHeight/2 }; + Vector2 v0 = { screenWidth/2.0f, screenHeight/2.0f }; Vector2 v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f }); Vector2 v2 = { 0 }; // Updated with mouse position @@ -97,17 +97,17 @@ int main(void) DrawCircleSector(v0, 40.0f, startangle, startangle - angle, 32, Fade(GREEN, 0.6f)); } - DrawText("v0", v0.x, v0.y, 10, DARKGRAY); + DrawText("v0", (int)v0.x, (int)v0.y, 10, DARKGRAY); // If the line from v0 to v1 would overlap the text, move it's position up 10 - if (angleMode == 0 && Vector2Subtract(v0, v1).y > 0.0f) DrawText("v1", v1.x, v1.y-10.0f, 10, DARKGRAY); - if (angleMode == 0 && Vector2Subtract(v0, v1).y < 0.0f) DrawText("v1", v1.x, v1.y, 10, DARKGRAY); + if (angleMode == 0 && Vector2Subtract(v0, v1).y > 0.0f) DrawText("v1", (int)v1.x, (int)v1.y-10, 10, DARKGRAY); + if (angleMode == 0 && Vector2Subtract(v0, v1).y < 0.0f) DrawText("v1", (int)v1.x, (int)v1.y, 10, DARKGRAY); // If angle mode 1, use v1 to emphasize the horizontal line - if (angleMode == 1) DrawText("v1", v0.x + 40.0f, v0.y, 10, DARKGRAY); + if (angleMode == 1) DrawText("v1", (int)v0.x + 40, (int)v0.y, 10, DARKGRAY); // position adjusted by -10 so it isn't hidden by cursor - DrawText("v2", v2.x-10.0f, v2.y-10.0f, 10, DARKGRAY); + DrawText("v2", (int)v2.x-10, (int)v2.y-10, 10, DARKGRAY); DrawText("Press SPACE to change MODE", 460, 10, 20, DARKGRAY); DrawText(TextFormat("ANGLE: %2.2f", angle), 10, 70, 20, LIME); diff --git a/examples/text/text_inline_styling.c b/examples/text/text_inline_styling.c index 865b1c5d0..b221c7e6f 100644 --- a/examples/text/text_inline_styling.c +++ b/examples/text/text_inline_styling.c @@ -86,7 +86,7 @@ int main(void) DrawTextStyled(GetFontDefault(), text, (Vector2){ 100, 220 }, 40.0f, 2.0f, BLACK); textSize = MeasureTextStyled(GetFontDefault(), text, 40.0f, 2.0f); - DrawRectangleLines(100, 220, textSize.x, textSize.y, GREEN); + DrawRectangleLines(100, 220, (int)textSize.x, (int)textSize.y, GREEN); EndDrawing(); //---------------------------------------------------------------------------------- @@ -154,7 +154,7 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float // Parse following color char colHexText[9] = { 0 }; - char *textPtr = &text[i]; // Color should start here, let's see... + const char *textPtr = &text[i]; // Color should start here, let's see... int colHexCount = 0; while ((textPtr != NULL) && (textPtr[colHexCount] != '\0') && (textPtr[colHexCount] != ']')) @@ -186,7 +186,7 @@ static void DrawTextStyled(Font font, const char *text, Vector2 position, float else increaseX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing); // Draw background rectangle color (if required) - if (colBack.a > 0) DrawRectangle(position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2*backRecPadding, colBack); + if (colBack.a > 0) DrawRectangleRec((Rectangle) { position.x + textOffsetX, position.y + textOffsetY - backRecPadding, increaseX, fontSize + 2 * backRecPadding }, colBack); if ((codepoint != ' ') && (codepoint != '\t')) { @@ -236,7 +236,7 @@ static Vector2 MeasureTextStyled(Font font, const char *text, float fontSize, fl { i += 2; // Skip "[c" or "[b" to start parsing color - char *textPtr = &text[i]; // Color should start here, let's see... + const char *textPtr = &text[i]; // Color should start here, let's see... int colHexCount = 0; while ((textPtr != NULL) && (textPtr[colHexCount] != '\0') && (textPtr[colHexCount] != ']')) diff --git a/examples/text/text_unicode_ranges.c b/examples/text/text_unicode_ranges.c index 2ed25e72f..e54c052b1 100644 --- a/examples/text/text_unicode_ranges.c +++ b/examples/text/text_unicode_ranges.c @@ -144,9 +144,9 @@ int main(void) // Draw font texture scaled to screen float atlasScale = 380.0f/font.texture.width; - DrawRectangle(400, 16, font.texture.width*atlasScale, font.texture.height*atlasScale, BLACK); - DrawTexturePro(font.texture, (Rectangle){ 0, 0, font.texture.width, font.texture.height }, - (Rectangle){ 400, 16, font.texture.width*atlasScale, font.texture.height*atlasScale }, (Vector2){ 0, 0 }, 0.0f, WHITE); + DrawRectangleRec((Rectangle) { 400.0f, 16.0f, font.texture.width* atlasScale, font.texture.height* atlasScale }, BLACK); + DrawTexturePro(font.texture, (Rectangle){ 0, 0, (float)font.texture.width, (float)font.texture.height }, + (Rectangle){ 400.0f, 16.0f, font.texture.width*atlasScale, font.texture.height*atlasScale }, (Vector2){ 0, 0 }, 0.0f, WHITE); DrawRectangleLines(400, 16, 380, 380, RED); DrawText(TextFormat("ATLAS SIZE: %ix%i px (x%02.2f)", font.texture.width, font.texture.height, atlasScale), 20, 380, 20, BLUE); diff --git a/examples/textures/textures_image_channel.c b/examples/textures/textures_image_channel.c index 29622b74d..e512af366 100644 --- a/examples/textures/textures_image_channel.c +++ b/examples/textures/textures_image_channel.c @@ -61,13 +61,13 @@ int main(void) UnloadImage(imageBlue); UnloadImage(backgroundImage); - Rectangle fudesumiRec = {0, 0, fudesumiImage.width, fudesumiImage.height}; + Rectangle fudesumiRec = {0, 0, (float)fudesumiImage.width, (float)fudesumiImage.height}; Rectangle fudesumiPos = {50, 10, fudesumiImage.width*0.8f, fudesumiImage.height*0.8f}; - Rectangle redPos = { 410, 10, fudesumiPos.width/2, fudesumiPos.height/2 }; - Rectangle greenPos = { 600, 10, fudesumiPos.width/2, fudesumiPos.height/2 }; - Rectangle bluePos = { 410, 230, fudesumiPos.width/2, fudesumiPos.height/2 }; - Rectangle alphaPos = { 600, 230, fudesumiPos.width/2, fudesumiPos.height/2 }; + Rectangle redPos = { 410, 10, fudesumiPos.width/2.0f, fudesumiPos.height/2.0f }; + Rectangle greenPos = { 600, 10, fudesumiPos.width/2.0f, fudesumiPos.height/2.0f }; + Rectangle bluePos = { 410, 230, fudesumiPos.width/2.0f, fudesumiPos.height/2.0f }; + Rectangle alphaPos = { 600, 230, fudesumiPos.width/2.0f, fudesumiPos.height/2.0f }; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/projects/VS2022/examples/core_delta_time.vcxproj b/projects/VS2022/examples/core_delta_time.vcxproj index 3d31afa42..1c488bb6f 100644 --- a/projects/VS2022/examples/core_delta_time.vcxproj +++ b/projects/VS2022/examples/core_delta_time.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {19CA0070-B4B2-4394-90B7-D0C259AA35BA} Win32Proj core_delta_time 10.0 diff --git a/projects/VS2022/examples/core_monitor_change.vcxproj b/projects/VS2022/examples/core_monitor_change.vcxproj index e372a68d0..07921bef3 100644 --- a/projects/VS2022/examples/core_monitor_change.vcxproj +++ b/projects/VS2022/examples/core_monitor_change.vcxproj @@ -51,7 +51,7 @@ - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} Win32Proj core_monitor_change 10.0 diff --git a/projects/VS2022/examples/models_geometry_textures_cube.vcxproj b/projects/VS2022/examples/models_geometry_textures_cube.vcxproj index 5c8452472..77fcd94d4 100644 --- a/projects/VS2022/examples/models_geometry_textures_cube.vcxproj +++ b/projects/VS2022/examples/models_geometry_textures_cube.vcxproj @@ -51,7 +51,7 @@ - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} + {A4662163-83E7-4309-8CAA-B0BF13655FE6} Win32Proj models_geometry_textures_cube 10.0 diff --git a/projects/VS2022/examples/shaders_ascii_rendering.vcxproj b/projects/VS2022/examples/shaders_ascii_rendering.vcxproj index 49ee10790..0bb37c6d8 100644 --- a/projects/VS2022/examples/shaders_ascii_rendering.vcxproj +++ b/projects/VS2022/examples/shaders_ascii_rendering.vcxproj @@ -51,7 +51,7 @@ - {9DB1F875-6E65-4195-B23F-ED8095C0B99C} + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20} Win32Proj shaders_ascii_rendering 10.0 diff --git a/projects/VS2022/examples/shapes_dashed_line.vcxproj b/projects/VS2022/examples/shapes_dashed_line.vcxproj index 4a4b86ef3..a5d4c3e1a 100644 --- a/projects/VS2022/examples/shapes_dashed_line.vcxproj +++ b/projects/VS2022/examples/shapes_dashed_line.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {8E132D5A-2C00-48D0-8747-97E41356F26F} Win32Proj shapes_dashed_line 10.0 diff --git a/projects/VS2022/examples/shapes_digital_clock.vcxproj b/projects/VS2022/examples/shapes_digital_clock.vcxproj index e361eb190..c2a201a12 100644 --- a/projects/VS2022/examples/shapes_digital_clock.vcxproj +++ b/projects/VS2022/examples/shapes_digital_clock.vcxproj @@ -292,7 +292,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNING;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) CompileAsC $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) @@ -309,7 +309,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNING;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) CompileAsC $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) /FS %(AdditionalOptions) @@ -345,7 +345,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNING;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) CompileAsC $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) @@ -366,7 +366,7 @@ Level3 Disabled - WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNING;WIN32;_DEBUG;_CONSOLE;PLATFORM_DESKTOP;%(PreprocessorDefinitions) CompileAsC $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) @@ -410,7 +410,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + _CRT_SECURE_NO_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) CompileAsC true @@ -432,7 +432,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + _CRT_SECURE_NO_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) CompileAsC true @@ -476,7 +476,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + _CRT_SECURE_NO_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) CompileAsC true @@ -504,7 +504,7 @@ MaxSpeed true true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP + _CRT_SECURE_NO_WARNING;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);PLATFORM_DESKTOP $(SolutionDir)..\..\src;%(AdditionalIncludeDirectories) CompileAsC true diff --git a/projects/VS2022/examples/shapes_kaleidoscope.vcxproj b/projects/VS2022/examples/shapes_kaleidoscope.vcxproj index 1fe3e7a70..52fa68e53 100644 --- a/projects/VS2022/examples/shapes_kaleidoscope.vcxproj +++ b/projects/VS2022/examples/shapes_kaleidoscope.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {0C442799-B09C-4CD1-9538-711B6E85E9BF} Win32Proj shapes_kaleidoscope 10.0 diff --git a/projects/VS2022/examples/shapes_recursive_tree.vcxproj b/projects/VS2022/examples/shapes_recursive_tree.vcxproj new file mode 100644 index 000000000..771860844 --- /dev/null +++ b/projects/VS2022/examples/shapes_recursive_tree.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {DFB40A10-F8B7-412A-BCC3-5EE49294D816} + Win32Proj + shapes_recursive_tree + 10.0 + shapes_recursive_tree + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + + + + Level3 + Disabled + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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;shcore.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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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/examples/shapes_triangle_strip.vcxproj b/projects/VS2022/examples/shapes_triangle_strip.vcxproj new file mode 100644 index 000000000..b128c0ff6 --- /dev/null +++ b/projects/VS2022/examples/shapes_triangle_strip.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {BB58A5FB-1A35-4471-86D0-A5189EC541B3} + Win32Proj + shapes_triangle_strip + 10.0 + shapes_triangle_strip + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/web_basic_window.vcxproj b/projects/VS2022/examples/web_basic_window.vcxproj index e36012ac6..6c0c7ab1f 100644 --- a/projects/VS2022/examples/web_basic_window.vcxproj +++ b/projects/VS2022/examples/web_basic_window.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC} Win32Proj web_basic_window 10.0 diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 0c710a731..f72cd64a9 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -347,7 +347,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_undo_redo", "examples\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_input_actions", "examples\core_input_actions.vcxproj", "{718FCBD0-591D-448C-B7D5-9F1CA8544E7B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_delta_time", "examples\core_delta_time.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_delta_time", "examples\core_delta_time.vcxproj", "{19CA0070-B4B2-4394-90B7-D0C259AA35BA}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_bullet_hell", "examples\shapes_bullet_hell.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" EndProject @@ -355,22 +355,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_vector_angle", "exam EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_basic_voxel", "examples\models_basic_voxel.vcxproj", "{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_dashed_line", "examples\shapes_dashed_line.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_dashed_line", "examples\shapes_dashed_line.vcxproj", "{8E132D5A-2C00-48D0-8747-97E41356F26F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_geometry_textures_cube", "examples\models_geometry_textures_cube.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_geometry_textures_cube", "examples\models_geometry_textures_cube.vcxproj", "{A4662163-83E7-4309-8CAA-B0BF13655FE6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{9DB1F875-6E65-4195-B23F-ED8095C0B99C}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{5F4B766F-DD52-4B53-B6C3-BC7611E17F20}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_change", "examples\core_monitor_change.vcxproj", "{52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_change", "examples\core_monitor_change.vcxproj", "{FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "web_basic_window", "examples\web_basic_window.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "web_basic_window", "examples\web_basic_window.vcxproj", "{A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{0C442799-B09C-4CD1-9538-711B6E85E9BF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{DFB40A10-F8B7-412A-BCC3-5EE49294D816}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{BB58A5FB-1A35-4471-86D0-A5189EC541B3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4297,30 +4299,30 @@ Global {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x64.Build.0 = Release|x64 {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x86.ActiveCfg = Release|Win32 {718FCBD0-591D-448C-B7D5-9F1CA8544E7B}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|ARM64.Build.0 = Debug|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|x64.ActiveCfg = Debug|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|x64.Build.0 = Debug|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|x86.ActiveCfg = Debug|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Debug|x86.Build.0 = Debug|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|ARM64.ActiveCfg = Release|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|ARM64.Build.0 = Release|ARM64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|x64.ActiveCfg = Release|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|x64.Build.0 = Release|x64 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|x86.ActiveCfg = Release|Win32 + {19CA0070-B4B2-4394-90B7-D0C259AA35BA}.Release|x86.Build.0 = Release|Win32 {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 @@ -4393,202 +4395,202 @@ Global {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.Build.0 = Debug|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.ActiveCfg = Debug|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.Build.0 = Debug|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.ActiveCfg = Debug|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.Build.0 = Debug|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.ActiveCfg = Release|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.Build.0 = Release|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.ActiveCfg = Release|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.Build.0 = Release|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.ActiveCfg = Release|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.Build.0 = Release|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.Build.0 = Debug|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.ActiveCfg = Debug|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.Build.0 = Debug|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.ActiveCfg = Debug|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.Build.0 = Debug|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.ActiveCfg = Release|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.Build.0 = Release|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.ActiveCfg = Release|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.Build.0 = Debug|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.ActiveCfg = Debug|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.Build.0 = Debug|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.ActiveCfg = Debug|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.Build.0 = Debug|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.Build.0 = Release|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.ActiveCfg = Release|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.Build.0 = Release|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.ActiveCfg = Release|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.Build.0 = Release|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.Build.0 = Debug|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.ActiveCfg = Debug|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.Build.0 = Debug|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.ActiveCfg = Debug|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.Build.0 = Debug|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.ActiveCfg = Release|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.Build.0 = Release|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.ActiveCfg = Release|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.Build.0 = Release|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.ActiveCfg = Release|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.Build.0 = Release|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.Build.0 = Debug|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.ActiveCfg = Debug|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.Build.0 = Debug|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.ActiveCfg = Debug|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.Build.0 = Debug|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.ActiveCfg = Release|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.Build.0 = Release|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.ActiveCfg = Release|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.Build.0 = Release|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.ActiveCfg = Release|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.Build.0 = Release|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.Build.0 = Debug|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.ActiveCfg = Debug|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.Build.0 = Debug|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.ActiveCfg = Debug|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.Build.0 = Debug|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.ActiveCfg = Release|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.Build.0 = Release|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.ActiveCfg = Release|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.Build.0 = Release|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.ActiveCfg = Release|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.Build.0 = Release|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.Build.0 = Debug|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.ActiveCfg = Debug|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.Build.0 = Debug|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.ActiveCfg = Debug|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.Build.0 = Debug|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.ActiveCfg = Release|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.Build.0 = Release|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.ActiveCfg = Release|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.Build.0 = Release|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.ActiveCfg = Release|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.Build.0 = Release|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.Build.0 = Debug|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.ActiveCfg = Debug|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.Build.0 = Debug|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.ActiveCfg = Debug|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.Build.0 = Debug|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.ActiveCfg = Release|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.Build.0 = Release|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.ActiveCfg = Release|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.Build.0 = Release|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.ActiveCfg = Release|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.Build.0 = Release|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.Build.0 = Debug|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.ActiveCfg = Debug|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.Build.0 = Debug|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.ActiveCfg = Debug|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.Build.0 = Debug|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.ActiveCfg = Release|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.Build.0 = Release|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.ActiveCfg = Release|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.Build.0 = Release|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.ActiveCfg = Release|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.Build.0 = Release|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.Build.0 = Debug|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.ActiveCfg = Debug|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.Build.0 = Debug|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.ActiveCfg = Debug|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.Build.0 = Debug|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.ActiveCfg = Release|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.Build.0 = Release|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.ActiveCfg = Release|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.Build.0 = Release|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.ActiveCfg = Release|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection GlobalSection(NestedProjects) = preSolution {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} {278D8859-20B1-428F-8448-064F46E1F021} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} @@ -4752,7 +4754,7 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} @@ -4760,19 +4762,21 @@ Global {D496308F-3C3C-40B3-A3ED-EA327D244B3E} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {3B27F358-2679-4F38-B297-17B536F580BB} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {718FCBD0-591D-448C-B7D5-9F1CA8544E7B} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} - {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {278D8859-20B1-428F-8448-064F46E1F021} - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} - EndGlobalSection -EndGlobal + {8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021} + {A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {0C442799-B09C-4CD1-9538-711B6E85E9BF} = {278D8859-20B1-428F-8448-064F46E1F021} + {DFB40A10-F8B7-412A-BCC3-5EE49294D816} = {278D8859-20B1-428F-8448-064F46E1F021} + {BB58A5FB-1A35-4471-86D0-A5189EC541B3} = {278D8859-20B1-428F-8448-064F46E1F021} + {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} + EndGlobalSection +EndGlobal diff --git a/src/rcore.c b/src/rcore.c index ccc02ab28..3b2535250 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -161,10 +161,8 @@ #endif // Platform specific defines to handle GetApplicationDirectory() -#if (defined(_WIN32)) - #ifndef MAX_PATH - #define MAX_PATH 1025 - #endif +#if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW)) + struct HINSTANCE__; __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(struct HINSTANCE__ *hModule, char *lpFilename, unsigned long nSize); __declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(struct HINSTANCE__ *hModule, wchar_t *lpFilename, unsigned long nSize); From 17bc628fd9a290cc54c5aaf2a8ce74ec56569a27 Mon Sep 17 00:00:00 2001 From: JohnnyCena123 Date: Wed, 15 Oct 2025 20:07:41 +0300 Subject: [PATCH 010/102] [rcore] Add `ComputeSHA256()` function (#5264) * [rcore] Add `ComputeSHA256()` function * adjust function signatures * review issues * fix repeating 0 * fix mistake * fixed macro * remove undefs * review styling mismatches * rename `A0,1` to `SHA256_A0,1` --------- Co-authored-by: CrackedPixel <5776225+CrackedPixel@users.noreply.github.com> --- src/raylib.h | 7 ++-- src/rcore.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/raylib.h b/src/raylib.h index c57efc2e1..e4be11084 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1161,9 +1161,10 @@ 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 (includes NULL terminator), memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), 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) +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) +RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 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 3b2535250..f1c975c21 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -3078,6 +3078,108 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize) return hash; } +// Compute SHA-256 hash code +// NOTE: Returns a static int[8] array (32 bytes) +unsigned int *ComputeSHA256(unsigned char *data, int dataSize) +{ + #define ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int) * 8) - c))) + #define SHA256_A0(x) (ROTATE_RIGHT(x, 7) ^ ROTATE_RIGHT(x, 18) ^ (x >> 3)) + #define SHA256_A1(x) (ROTATE_RIGHT(x, 17) ^ ROTATE_RIGHT(x, 19) ^ (x >> 10)) + + static const unsigned int k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + + static unsigned int hash[8]; + hash[0] = 0x6A09e667; + hash[1] = 0xbb67ae85; + hash[2] = 0x3c6ef372; + hash[3] = 0xa54ff53a; + hash[4] = 0x510e527f; + hash[5] = 0x9b05688c; + hash[6] = 0x1f83d9ab; + hash[7] = 0x5be0cd19; + + const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8; + unsigned long long int paddedSize = dataSize + sizeof(dataSize); + paddedSize += (64 - (paddedSize%64)); + unsigned char *buffer = RL_CALLOC(paddedSize, sizeof(unsigned char)); + + memcpy(buffer, data, dataSize); + buffer[dataSize] = 0x80; + for (int i = 1; i <= sizeof(bitLen); i++) + buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF; + + for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++) + { + 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]; + unsigned int f = hash[5]; + unsigned int g = hash[6]; + unsigned int h = hash[7]; + + unsigned char *block = buffer + (blockN*64); + unsigned int w[64]; + for (int i = 0; i < 16; i++) + { + w[i] = + ((unsigned int)block[i*4 + 0] << 24) | + ((unsigned int)block[i*4 + 1] << 16) | + ((unsigned int)block[i*4 + 2] << 8) | + ((unsigned int)block[i*4 + 3]); + } + for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16]; + + for (unsigned long long int t = 0; t < 64; t++) + { + unsigned int e1 = (ROTATE_RIGHT(e, 6) ^ ROTATE_RIGHT(e, 11) ^ ROTATE_RIGHT(e, 25)); + unsigned int ch = ((e & f) ^ (~e & g)); + unsigned int t1 = (h + e1 + ch + k[t] + w[t]); + unsigned int e0 = (ROTATE_RIGHT(a, 2) ^ ROTATE_RIGHT(a, 13) ^ ROTATE_RIGHT(a, 22)); + unsigned int maj = ((a & b) ^ (a & c) ^ (b & c)); + unsigned int t2 = e0 + maj; + + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + hash[0] += a; + hash[1] += b; + hash[2] += c; + hash[3] += d; + hash[4] += e; + hash[5] += f; + hash[6] += g; + hash[7] += h; + } + RL_FREE(buffer); + return hash; +} + //---------------------------------------------------------------------------------- // Module Functions Definition: Automation Events Recording and Playing //---------------------------------------------------------------------------------- From adfe2c170412751d8dced8b306553c6d95454fa7 Mon Sep 17 00:00:00 2001 From: Saksham Goyal Date: Wed, 15 Oct 2025 13:11:44 -0400 Subject: [PATCH 011/102] C++ compiler support v2 (#5252) * Get C++ compilers working * Fix Formatting --- .gitignore | 3 +++ src/external/RGFW.h | 4 +-- src/external/glfw/src/context.c | 17 ++++++------- src/external/glfw/src/egl_context.c | 11 ++++----- src/external/jar_mod.h | 8 +++--- src/external/jar_xm.h | 38 ++++++++++++++--------------- src/external/qoa.h | 6 ++--- src/external/qoaplay.c | 4 +-- src/external/tinyobj_loader_c.h | 2 +- src/external/vox_loader.h | 18 +++++++------- src/external/win32_clipboard.h | 13 ++-------- src/platforms/rcore_desktop_glfw.c | 12 +++++---- src/platforms/rcore_desktop_rgfw.c | 20 ++++++++++----- src/raudio.c | 8 +++--- src/rcore.c | 10 ++++++-- src/rgestures.h | 2 +- src/rmodels.c | 14 +++++------ src/rtext.c | 4 +-- src/rtextures.c | 7 +++--- src/utils.c | 2 +- 20 files changed, 106 insertions(+), 97 deletions(-) diff --git a/.gitignore b/.gitignore index ac4f016e4..fa4c4c49d 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,8 @@ packages/ *.so *.so.* *.dll +*.h.pch +./*.obj # Emscripten emsdk @@ -81,6 +83,7 @@ DerivedData/ # VSCode project .vscode +.clangd # Jetbrains project .idea/ diff --git a/src/external/RGFW.h b/src/external/RGFW.h index 8bd9b5709..7205bf9d8 100644 --- a/src/external/RGFW.h +++ b/src/external/RGFW.h @@ -7727,8 +7727,8 @@ RGFW_bool RGFW_monitor_requestMode(RGFW_monitor mon, RGFW_monitorMode mode, RGFW dm.dmBitsPerPel = (DWORD)(mode.red + mode.green + mode.blue); } - if (ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) { - if (ChangeDisplaySettingsEx(dd.DeviceName, &dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) + if (ChangeDisplaySettingsExA((LPCSTR)dd.DeviceName, (DEVMODE *)&dm, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL) { + if (ChangeDisplaySettingsExA((LPCSTR)dd.DeviceName, (DEVMODE *)&dm, NULL, CDS_UPDATEREGISTRY, NULL) == DISP_CHANGE_SUCCESSFUL) return RGFW_TRUE; return RGFW_FALSE; } else return RGFW_FALSE; diff --git a/src/external/glfw/src/context.c b/src/external/glfw/src/context.c index cc1fac4f3..bcb2b51b8 100644 --- a/src/external/glfw/src/context.c +++ b/src/external/glfw/src/context.c @@ -359,7 +359,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, window->context.source = ctxconfig->source; window->context.client = GLFW_OPENGL_API; - previous = _glfwPlatformGetTls(&_glfw.contextSlot); + previous = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); glfwMakeContextCurrent((GLFWwindow*) window); if (_glfwPlatformGetTls(&_glfw.contextSlot) != window) return GLFW_FALSE; @@ -615,12 +615,12 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* window = (_GLFWwindow *) handle; _GLFWwindow* previous; _GLFW_REQUIRE_INIT(); - previous = _glfwPlatformGetTls(&_glfw.contextSlot); + previous = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); if (window && window->context.client == GLFW_NO_API) { @@ -642,12 +642,12 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI GLFWwindow* glfwGetCurrentContext(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return _glfwPlatformGetTls(&_glfw.contextSlot); + return (GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); } GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* window = (_GLFWwindow *) handle; assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -668,7 +668,7 @@ GLFWAPI void glfwSwapInterval(int interval) _GLFW_REQUIRE_INIT(); - window = _glfwPlatformGetTls(&_glfw.contextSlot); + window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, @@ -686,7 +686,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension) _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - window = _glfwPlatformGetTls(&_glfw.contextSlot); + window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, @@ -752,7 +752,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - window = _glfwPlatformGetTls(&_glfw.contextSlot); + window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, @@ -762,4 +762,3 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) return window->context.getProcAddress(procname); } - diff --git a/src/external/glfw/src/egl_context.c b/src/external/glfw/src/egl_context.c index ef65dd350..19ab3dfbe 100644 --- a/src/external/glfw/src/egl_context.c +++ b/src/external/glfw/src/egl_context.c @@ -118,10 +118,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, return GLFW_FALSE; } - nativeConfigs = _glfw_calloc(nativeCount, sizeof(EGLConfig)); + nativeConfigs = (EGLConfig *)_glfw_calloc(nativeCount, sizeof(EGLConfig)); eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); - usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); + usableConfigs = (_GLFWfbconfig *)_glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; for (i = 0; i < nativeCount; i++) @@ -308,7 +308,7 @@ static int extensionSupportedEGL(const char* extension) static GLFWglproc getProcAddressEGL(const char* procname) { - _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + _GLFWwindow* window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); assert(window != NULL); if (window->context.egl.client) @@ -883,7 +883,7 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void) GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* window = (_GLFWwindow *) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); if (window->context.source != GLFW_EGL_CONTEXT_API) @@ -897,7 +897,7 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* window = (_GLFWwindow *) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); if (window->context.source != GLFW_EGL_CONTEXT_API) @@ -908,4 +908,3 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) return window->context.egl.surface; } - diff --git a/src/external/jar_mod.h b/src/external/jar_mod.h index 2a220f8af..7ecf9f437 100644 --- a/src/external/jar_mod.h +++ b/src/external/jar_mod.h @@ -1148,7 +1148,7 @@ static bool jar_mod_load( jar_mod_context_t * modctx, void * mod_data, int mod_d { // 15 Samples modules support // Shift the whole datas to make it look likes a standard 4 channels mod. - memcopy(&(modctx->song.signature), "M.K.", 4); + memcopy(&(modctx->song.signature), (void *)"M.K.", 4); memcopy(&(modctx->song.length), &(modctx->song.samples[15]), 130); memclear(&(modctx->song.samples[15]), 0, 480); modmemory += 600; @@ -1535,13 +1535,13 @@ mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename) if(fsize && fsize < 32*1024*1024) { - modctx->modfile = JARMOD_MALLOC(fsize); + modctx->modfile = (muchar *) JARMOD_MALLOC(fsize); modctx->modfilesize = fsize; memset(modctx->modfile, 0, fsize); fread(modctx->modfile, fsize, 1, f); fclose(f); - - if(!jar_mod_load(modctx, (void*)modctx->modfile, fsize)) fsize = 0; + + if(!jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0; } else fsize = 0; } return fsize; diff --git a/src/external/jar_xm.h b/src/external/jar_xm.h index 174c1704c..849fe62f4 100644 --- a/src/external/jar_xm.h +++ b/src/external/jar_xm.h @@ -123,7 +123,7 @@ void jar_xm_generate_samples(jar_xm_context_t* ctx, float* output, size_t numsam // * @param output buffer of 2*numsamples elements (A left and right value for each sample) // * @param numsamples number of samples to generate void jar_xm_generate_samples_16bit(jar_xm_context_t* ctx, short* output, size_t numsamples) { - float* musicBuffer = JARXM_MALLOC((2*numsamples)*sizeof(float)); + float* musicBuffer = (float *)JARXM_MALLOC((2*numsamples)*sizeof(float)); jar_xm_generate_samples(ctx, musicBuffer, numsamples); if(output){ @@ -136,7 +136,7 @@ void jar_xm_generate_samples_16bit(jar_xm_context_t* ctx, short* output, size_t // * @param output buffer of 2*numsamples elements (A left and right value for each sample) // * @param numsamples number of samples to generate void jar_xm_generate_samples_8bit(jar_xm_context_t* ctx, char* output, size_t numsamples) { - float* musicBuffer = JARXM_MALLOC((2*numsamples)*sizeof(float)); + float* musicBuffer = (float *)JARXM_MALLOC((2*numsamples)*sizeof(float)); jar_xm_generate_samples(ctx, musicBuffer, numsamples); if(output){ @@ -543,7 +543,7 @@ int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, siz #endif bytes_needed = jar_xm_get_memory_needed_for_context(moddata, moddata_length); - mempool = JARXM_MALLOC(bytes_needed); + mempool = (char *)JARXM_MALLOC(bytes_needed); if(mempool == NULL && bytes_needed > 0) { /* JARXM_MALLOC() failed, trouble ahead */ DEBUG("call to JARXM_MALLOC() failed, returned %p", (void*)mempool); return 2; @@ -558,11 +558,11 @@ int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, siz ctx->rate = rate; mempool = jar_xm_load_module(ctx, moddata, moddata_length, mempool); - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); ctx->channels = (jar_xm_channel_context_t*)mempool; mempool += ctx->module.num_channels * sizeof(jar_xm_channel_context_t); - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); ctx->default_global_volume = 1.f; ctx->global_volume = ctx->default_global_volume; @@ -583,7 +583,7 @@ int jar_xm_create_context_safe(jar_xm_context_t** ctxp, const char* moddata, siz ch->actual_panning = .5f; } - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); ctx->row_loop_count = (uint8_t *)mempool; mempool += MAX_NUM_ROWS * sizeof(uint8_t); @@ -681,14 +681,14 @@ uint64_t jar_xm_get_latest_trigger_of_channel(jar_xm_context_t *ctx, uint16_t ch //* Bound reader macros. //* If we attempt to read the buffer out-of-bounds, pretend that the buffer is infinitely padded with zeroes. -#define READ_U8(offset) (((offset) < moddata_length) ? (*(uint8_t*)(moddata + (offset))) : 0) +#define READ_U8(offset) (((offset) < moddata_length) ? (*(uint8_t *)(moddata + (offset))) : 0) #define READ_U16(offset) ((uint16_t)READ_U8(offset) | ((uint16_t)READ_U8((offset) + 1) << 8)) #define READ_U32(offset) ((uint32_t)READ_U16(offset) | ((uint32_t)READ_U16((offset) + 2) << 16)) #define READ_MEMCPY(ptr, offset, length) memcpy_pad(ptr, length, moddata, moddata_length, offset) static void memcpy_pad(void *dst, size_t dst_len, const void *src, size_t src_len, size_t offset) { - uint8_t *dst_c = dst; - const uint8_t *src_c = src; + uint8_t *dst_c = (uint8_t *)dst; + const uint8_t *src_c = (uint8_t *)src; /* how many bytes can be copied without overrunning `src` */ size_t copy_bytes = (src_len >= offset) ? (src_len - offset) : 0; @@ -808,10 +808,10 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd mod->linear_interpolation = 1; // Linear interpolation can be set after loading mod->ramping = 1; // ramping can be set after loading mempool += mod->num_patterns * sizeof(jar_xm_pattern_t); - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); mod->instruments = (jar_xm_instrument_t*)mempool; mempool += mod->num_instruments * sizeof(jar_xm_instrument_t); - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); uint16_t flags = READ_U32(offset + 14); mod->frequency_type = (flags & (1 << 0)) ? jar_xm_LINEAR_FREQUENCIES : jar_xm_AMIGA_FREQUENCIES; ctx->default_tempo = READ_U16(offset + 16); @@ -884,7 +884,7 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd offset += packed_patterndata_size; } - mempool = ALIGN_PTR(mempool, 16); + mempool = (char *)ALIGN_PTR(mempool, 16); /* Read instruments */ for(uint16_t i = 0; i < ctx->module.num_instruments; ++i) { @@ -928,11 +928,11 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd instr->panning_envelope.enabled = flags & (1 << 0); instr->panning_envelope.sustain_enabled = flags & (1 << 1); instr->panning_envelope.loop_enabled = flags & (1 << 2); - instr->vibrato_type = READ_U8(offset + 235); + instr->vibrato_type = (jar_xm_waveform_type_t)READ_U8(offset + 235); if(instr->vibrato_type == 2) { - instr->vibrato_type = 1; + instr->vibrato_type = (jar_xm_waveform_type_t)1; } else if(instr->vibrato_type == 1) { - instr->vibrato_type = 2; + instr->vibrato_type = (jar_xm_waveform_type_t)2; } instr->vibrato_sweep = READ_U8(offset + 236); instr->vibrato_depth = READ_U8(offset + 237); @@ -976,7 +976,7 @@ char* jar_xm_load_module(jar_xm_context_t* ctx, const char* moddata, size_t modd sample->panning = (float)READ_U8(offset + 15) / 255.f; sample->relative_note = (int8_t)READ_U8(offset + 16); READ_MEMCPY(sample->name, 18, SAMPLE_NAME_LENGTH); - sample->data = (float*)mempool; + sample->data = (float *)mempool; if(sample->bits == 16) { /* 16 bit sample */ mempool += sample->length * (sizeof(float) >> 1); @@ -1475,7 +1475,7 @@ static void jar_xm_handle_note_and_instrument(jar_xm_context_t* ctx, jar_xm_chan jar_xm_pitch_slide(ctx, ch, ch->fine_portamento_down_param); break; case 4: /* E4y: Set vibrato control */ - ch->vibrato_waveform = s->effect_param & 3; + ch->vibrato_waveform = (jar_xm_waveform_type_t)(s->effect_param & 3); ch->vibrato_waveform_retrigger = !((s->effect_param >> 2) & 1); break; case 5: /* E5y: Set finetune */ @@ -1502,7 +1502,7 @@ static void jar_xm_handle_note_and_instrument(jar_xm_context_t* ctx, jar_xm_chan } break; case 7: /* E7y: Set tremolo control */ - ch->tremolo_waveform = s->effect_param & 3; + ch->tremolo_waveform = (jar_xm_waveform_type_t)(s->effect_param & 3); ch->tremolo_waveform_retrigger = !((s->effect_param >> 2) & 1); break; case 0xA: /* EAy: Fine volume slide up */ @@ -2223,7 +2223,7 @@ int jar_xm_create_context_from_file(jar_xm_context_t** ctx, uint32_t rate, const return 4; } - char* data = JARXM_MALLOC(size + 1); + char* data = (char *)JARXM_MALLOC(size + 1); if(!data || fread(data, 1, size, xmf) < size) { fclose(xmf); DEBUG_ERR(data ? "fread() failed" : "JARXM_MALLOC() failed"); diff --git a/src/external/qoa.h b/src/external/qoa.h index f0f44214d..57b85d131 100644 --- a/src/external/qoa.h +++ b/src/external/qoa.h @@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len) num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */ num_slices * 8 * qoa->channels; /* 8 byte slices */ - unsigned char *bytes = QOA_MALLOC(encoded_size); + unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size); for (unsigned int c = 0; c < qoa->channels; c++) { /* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the @@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) { /* Calculate the required size of the sample buffer and allocate */ int total_samples = qoa->samples * qoa->channels; - short *sample_data = QOA_MALLOC(total_samples * sizeof(short)); + short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short)); unsigned int sample_index = 0; unsigned int frame_len; @@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) { bytes_read = fread(data, 1, size, f); fclose(f); - sample_data = qoa_decode(data, bytes_read, qoa); + sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa); QOA_FREE(data); return sample_data; } diff --git a/src/external/qoaplay.c b/src/external/qoaplay.c index 4378e5ebd..0ac6f6c06 100644 --- a/src/external/qoaplay.c +++ b/src/external/qoaplay.c @@ -104,7 +104,7 @@ qoaplay_desc *qoaplay_open(const char *path) // + a buffer to hold one frame of encoded data unsigned int buffer_size = qoa_max_frame_size(&qoa); unsigned int sample_data_size = qoa.channels*QOA_FRAME_LEN*sizeof(short)*2; - qoaplay_desc *qoa_ctx = QOA_MALLOC(sizeof(qoaplay_desc) + buffer_size + sample_data_size); + qoaplay_desc *qoa_ctx = (qoaplay_desc *)QOA_MALLOC(sizeof(qoaplay_desc) + buffer_size + sample_data_size); memset(qoa_ctx, 0, sizeof(qoaplay_desc)); qoa_ctx->file = file; @@ -136,7 +136,7 @@ qoaplay_desc *qoaplay_open_memory(const unsigned char *data, int data_size) // + the sample data for one frame // + a buffer to hold one frame of encoded data unsigned int sample_data_size = qoa.channels*QOA_FRAME_LEN*sizeof(short)*2; - qoaplay_desc *qoa_ctx = QOA_MALLOC(sizeof(qoaplay_desc) + sample_data_size + data_size); + qoaplay_desc *qoa_ctx = (qoaplay_desc *)QOA_MALLOC(sizeof(qoaplay_desc) + sample_data_size + data_size); memset(qoa_ctx, 0, sizeof(qoaplay_desc)); qoa_ctx->file = NULL; diff --git a/src/external/tinyobj_loader_c.h b/src/external/tinyobj_loader_c.h index 55d595a69..88b2acbdc 100644 --- a/src/external/tinyobj_loader_c.h +++ b/src/external/tinyobj_loader_c.h @@ -454,7 +454,7 @@ static void parseFloat3(float *x, float *y, float *z, const char **token) { } static unsigned int my_strnlen(const char *s, unsigned int n) { - const char *p = memchr(s, 0, n); + const char *p = (const char *)memchr(s, 0, n); return p ? (unsigned int)(p - s) : n; } diff --git a/src/external/vox_loader.h b/src/external/vox_loader.h index 0d328c078..6d933907c 100644 --- a/src/external/vox_loader.h +++ b/src/external/vox_loader.h @@ -151,7 +151,7 @@ void Vox_FreeArrays(VoxArray3D* voxarray); ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // Implementation -///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// #ifdef VOX_LOADER_IMPLEMENTATION @@ -165,7 +165,7 @@ void Vox_FreeArrays(VoxArray3D* voxarray); static void initArrayUShort(ArrayUShort* a, int initialSize) { - a->array = VOX_MALLOC(initialSize * sizeof(unsigned short)); + a->array = (unsigned short *)VOX_MALLOC(initialSize * sizeof(unsigned short)); a->used = 0; a->size = initialSize; } @@ -175,7 +175,7 @@ static void insertArrayUShort(ArrayUShort* a, unsigned short element) if (a->used == a->size) { a->size *= 2; - a->array = VOX_REALLOC(a->array, a->size * sizeof(unsigned short)); + a->array = (unsigned short *)VOX_REALLOC(a->array, a->size * sizeof(unsigned short)); } a->array[a->used++] = element; } @@ -194,7 +194,7 @@ static void freeArrayUShort(ArrayUShort* a) static void initArrayVector3(ArrayVector3* a, int initialSize) { - a->array = VOX_MALLOC(initialSize * sizeof(VoxVector3)); + a->array = (VoxVector3 *)VOX_MALLOC(initialSize * sizeof(VoxVector3)); a->used = 0; a->size = initialSize; } @@ -204,7 +204,7 @@ static void insertArrayVector3(ArrayVector3* a, VoxVector3 element) if (a->used == a->size) { a->size *= 2; - a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxVector3)); + a->array = (VoxVector3 *)VOX_REALLOC(a->array, a->size * sizeof(VoxVector3)); } a->array[a->used++] = element; } @@ -222,7 +222,7 @@ static void freeArrayVector3(ArrayVector3* a) static void initArrayColor(ArrayColor* a, int initialSize) { - a->array = VOX_MALLOC(initialSize * sizeof(VoxColor)); + a->array = (VoxColor *)VOX_MALLOC(initialSize * sizeof(VoxColor)); a->used = 0; a->size = initialSize; } @@ -232,7 +232,7 @@ static void insertArrayColor(ArrayColor* a, VoxColor element) if (a->used == a->size) { a->size *= 2; - a->array = VOX_REALLOC(a->array, a->size * sizeof(VoxColor)); + a->array = (VoxColor *)VOX_REALLOC(a->array, a->size * sizeof(VoxColor)); } a->array[a->used++] = element; } @@ -327,7 +327,7 @@ static void Vox_AllocArray(VoxArray3D* pvoxarray, int _sx, int _sy, int _sz) // Alloc chunks array int size = sizeof(CubeChunk3D) * chx * chy * chz; - pvoxarray->m_arrayChunks = VOX_MALLOC(size); + pvoxarray->m_arrayChunks = (CubeChunk3D *)VOX_MALLOC(size); pvoxarray->arrayChunksSize = size; // Init chunks array @@ -366,7 +366,7 @@ static void Vox_SetVoxel(VoxArray3D* pvoxarray, int x, int y, int z, unsigned ch if (chunk->m_array == 0) { int size = CHUNKSIZE * CHUNKSIZE * CHUNKSIZE; - chunk->m_array = VOX_MALLOC(size); + chunk->m_array = (unsigned char *)VOX_MALLOC(size); chunk->arraySize = size; memset(chunk->m_array, 0, size); diff --git a/src/external/win32_clipboard.h b/src/external/win32_clipboard.h index 832856432..1f9a27521 100644 --- a/src/external/win32_clipboard.h +++ b/src/external/win32_clipboard.h @@ -13,7 +13,7 @@ unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long #include #include -// NOTE: These search for architecture is taken from "Windows.h", and it's necessary if we really don't wanna import windows.h +// NOTE: These search for architecture is taken from "Windows.h", and it's necessary if we really don't wanna import windows.h // and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. ) can cause problems is these are not defined. #if !defined(_X86_) && !defined(_68K_) && !defined(_MPPC_) && !defined(_IA64_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) && !defined(_ARM64EC_) && defined(_M_IX86) #define _X86_ @@ -93,14 +93,6 @@ unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long typedef int WINBOOL; - -// typedef HANDLE HGLOBAL; - -#ifndef HWND -#define HWND void* -#endif - - #if !defined(_WINUSER_) || !defined(WINUSER_ALREADY_INCLUDED) WINUSERAPI WINBOOL WINAPI OpenClipboard(HWND hWndNewOwner); WINUSERAPI WINBOOL WINAPI CloseClipboard(VOID); @@ -284,7 +276,7 @@ unsigned char* Win32GetClipboardImageData(int* width, int* height, unsigned long // This may be wrong since we might be allocating in a DLL and freeing from another module, the main application // that may cause heap corruption. We could create a FreeImage function // - bmpData = malloc(sizeof(bmpFileHeader) + clipDataSize); + bmpData = (BYTE *)malloc(sizeof(bmpFileHeader) + clipDataSize); // First we add the header for a bmp file memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader)); // Then we add the header for the bmp itself + the pixel data @@ -371,4 +363,3 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih) } #endif // WIN32_CLIPBOARD_IMPLEMENTATION // EOF - diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index a9ee199c6..0144f623d 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -56,10 +56,12 @@ // Support retrieving native window handlers #if defined(_WIN32) - typedef void *PVOID; - typedef PVOID HANDLE; + #if !defined(HWND) && !defined(_MSVC_LANG) + #define HWND void* + #elif !defined(HWND) && defined(_MSVC_LANG) + typedef struct HWND__ *HWND; + #endif #include "../external/win32_clipboard.h" - typedef HANDLE HWND; #define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h #include "GLFW/glfw3native.h" @@ -1031,7 +1033,7 @@ Image GetClipboardImage(void) fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); - else image = LoadImageFromMemory(".bmp", fileData, (int)dataSize); + else image = LoadImageFromMemory(".bmp", (const unsigned char*)fileData, (int)dataSize); #else TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform"); #endif @@ -1353,8 +1355,8 @@ int InitPlatform(void) const GLFWallocator allocator = { .allocate = AllocateWrapper, - .deallocate = DeallocateWrapper, .reallocate = ReallocateWrapper, + .deallocate = DeallocateWrapper, .user = NULL, // RL_*ALLOC macros are not capable of handling user-provided data }; diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 8c4deeb9a..52ec6ac94 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -83,7 +83,14 @@ void CloseWindow(void); #undef MAX_PATH +#if defined(__cplusplus) +extern "C" { +#endif __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, const char *lpMultiByteStr, int cbMultiByte, wchar_t *lpWideCharStr, int cchWideChar); +#if defined(__cplusplus) +} +#endif + #endif #if defined(__APPLE__) @@ -564,7 +571,7 @@ int RGFW_formatToChannels(int format) // Set icon for window void SetWindowIcon(Image image) { - RGFW_window_setIcon(platform.window, image.data, RGFW_AREA(image.width, image.height), RGFW_formatToChannels(image.format)); + RGFW_window_setIcon(platform.window, (u8 *)image.data, RGFW_AREA(image.width, image.height), RGFW_formatToChannels(image.format)); } // Set icon for window @@ -585,8 +592,8 @@ void SetWindowIcons(Image *images, int count) if ((smallIcon == NULL) || ((images[i].width < smallIcon->width) && (images[i].height > smallIcon->height))) smallIcon = &images[i]; } - if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow); - if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar); + if (smallIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)smallIcon->data, RGFW_AREA(smallIcon->width, smallIcon->height), RGFW_formatToChannels(smallIcon->format), RGFW_iconWindow); + if (bigIcon != NULL) RGFW_window_setIconEx(platform.window, (u8 *)bigIcon->data, RGFW_AREA(bigIcon->width, bigIcon->height), RGFW_formatToChannels(bigIcon->format), RGFW_iconTaskbar); } } @@ -805,7 +812,7 @@ Image GetClipboardImage(void) fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data"); - else image = LoadImageFromMemory(".bmp", fileData, dataSize); + else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize); #else TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS"); #endif @@ -1418,7 +1425,8 @@ void ClosePlatform(void) // Keycode mapping static KeyboardKey ConvertScancodeToKey(u32 keycode) { - if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return 0; + if (keycode > sizeof(keyMappingRGFW)/sizeof(unsigned short)) return KEY_NULL; - return keyMappingRGFW[keycode]; + return (KeyboardKey)keyMappingRGFW[keycode]; } + diff --git a/src/raudio.c b/src/raudio.c index 798c062e9..ca63b3aac 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -575,7 +575,7 @@ AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam return NULL; } - if (sizeInFrames > 0) audioBuffer->data = RL_CALLOC(sizeInFrames*channels*ma_get_bytes_per_sample(format), 1); + if (sizeInFrames > 0) audioBuffer->data = (unsigned char *)RL_CALLOC(sizeInFrames*channels*ma_get_bytes_per_sample(format), 1); // Audio data runs through a format converter ma_data_converter_config converterConfig = ma_data_converter_config_init(format, AUDIO_DEVICE_FORMAT, channels, AUDIO_DEVICE_CHANNELS, sampleRate, AUDIO.System.device.sampleRate); @@ -808,7 +808,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short)); // NOTE: We are forcing conversion to 16bit sample size on reading - drwav_read_pcm_frames_s16(&wav, wave.frameCount, wave.data); + drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data); } else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data"); @@ -1091,7 +1091,7 @@ bool ExportWave(Wave wave, const char *fileName) qoa.samplerate = wave.sampleRate; qoa.samples = wave.frameCount; - int bytesWritten = qoa_write(fileName, wave.data, &qoa); + int bytesWritten = qoa_write(fileName, (const short *)wave.data, &qoa); if (bytesWritten > 0) success = true; } else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export"); @@ -2079,7 +2079,7 @@ float GetMusicTimePlayed(Music music) { uint64_t framesPlayed = 0; - jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &framesPlayed); + jar_xm_get_position((jar_xm_context_t *)music.ctxData, NULL, NULL, NULL, &framesPlayed); secondsPlayed = (float)framesPlayed/music.stream.sampleRate; } else diff --git a/src/rcore.c b/src/rcore.c index f1c975c21..f87b68783 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -164,11 +164,17 @@ #if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW)) struct HINSTANCE__; +#if defined(__cplusplus) +extern "C" { +#endif __declspec(dllimport) unsigned long __stdcall GetModuleFileNameA(struct HINSTANCE__ *hModule, char *lpFilename, unsigned long nSize); __declspec(dllimport) unsigned long __stdcall GetModuleFileNameW(struct HINSTANCE__ *hModule, wchar_t *lpFilename, unsigned long nSize); __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); __declspec(dllimport) unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod); __declspec(dllimport) unsigned int __stdcall timeEndPeriod(unsigned int uPeriod); +#if defined(__cplusplus) +} +#endif #elif defined(__linux__) #include #elif defined(__FreeBSD__) @@ -2328,8 +2334,8 @@ const char *GetApplicationDirectory(void) int len = 0; #if defined(UNICODE) unsigned short widePath[MAX_PATH]; - len = GetModuleFileNameW(NULL, widePath, MAX_PATH); - len = WideCharToMultiByte(0, 0, widePath, len, appDir, MAX_PATH, NULL, NULL); + len = GetModuleFileNameW(NULL, (wchar_t *)widePath, MAX_PATH); + len = WideCharToMultiByte(0, 0, (wchar_t *)widePath, len, appDir, MAX_PATH, NULL, NULL); #else len = GetModuleFileNameA(NULL, appDir, MAX_PATH); #endif diff --git a/src/rgestures.h b/src/rgestures.h index 389df64a1..f601a4790 100644 --- a/src/rgestures.h +++ b/src/rgestures.h @@ -232,8 +232,8 @@ typedef struct { // Global Variables Definition //---------------------------------------------------------------------------------- static GesturesData GESTURES = { - .Touch.firstId = -1, .current = GESTURE_NONE, // No current gesture detected + .Touch.firstId = -1, .enabledFlags = 0b0000001111111111 // All gestures supported by default }; diff --git a/src/rmodels.c b/src/rmodels.c index f800ad1b1..3a5cc9004 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -5179,7 +5179,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo // Release file data callback for cgltf static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data) { - UnloadFileData(data); + UnloadFileData((unsigned char *)data); } // Load image from different glTF provided methods (uri, path, buffer_view) @@ -6140,7 +6140,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ float tmp[3] = { 0.0f }; cgltf_accessor_read_float(output, keyframe, tmp, 3); Vector3 v1 = {tmp[0], tmp[1], tmp[2]}; - Vector3 *r = data; + Vector3 *r = (Vector3 *)data; *r = v1; } break; @@ -6151,7 +6151,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ Vector3 v1 = {tmp[0], tmp[1], tmp[2]}; cgltf_accessor_read_float(output, keyframe+1, tmp, 3); Vector3 v2 = {tmp[0], tmp[1], tmp[2]}; - Vector3 *r = data; + Vector3 *r = (Vector3 *)data; *r = Vector3Lerp(v1, v2, t); } break; @@ -6166,7 +6166,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ Vector3 v2 = {tmp[0], tmp[1], tmp[2]}; cgltf_accessor_read_float(output, 3*(keyframe+1), tmp, 3); Vector3 tangent2 = {tmp[0], tmp[1], tmp[2]}; - Vector3 *r = data; + Vector3 *r = (Vector3 *)data; *r = Vector3CubicHermite(v1, tangent1, v2, tangent2, t); } break; @@ -6183,7 +6183,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ float tmp[4] = { 0.0f }; cgltf_accessor_read_float(output, keyframe, tmp, 4); Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]}; - Vector4 *r = data; + Vector4 *r = (Vector4 *)data; *r = v1; } break; @@ -6194,7 +6194,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ Vector4 v1 = {tmp[0], tmp[1], tmp[2], tmp[3]}; cgltf_accessor_read_float(output, keyframe+1, tmp, 4); Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]}; - Vector4 *r = data; + Vector4 *r = (Vector4 *)data; *r = QuaternionSlerp(v1, v2, t); } break; @@ -6209,7 +6209,7 @@ static bool GetPoseAtTimeGLTF(cgltf_interpolation_type interpolationType, cgltf_ 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], 0.0f}; - Vector4 *r = data; + Vector4 *r = (Vector4 *)data; v1 = QuaternionNormalize(v1); v2 = QuaternionNormalize(v2); diff --git a/src/rtext.c b/src/rtext.c index 6a87fe3db..9951dc66d 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1731,7 +1731,7 @@ char *TextReplace(const char *text, const char *search, const char *replacement) // - 'text' points to the remainder of text after "end of replace" while (count--) { - insertPoint = strstr(text, search); + insertPoint = (char *)strstr(text, search); lastReplacePos = (int)(insertPoint - text); temp = strncpy(temp, text, lastReplacePos) + lastReplacePos; temp = strcpy(temp, replacement) + replaceLen; @@ -1887,7 +1887,7 @@ int TextFindIndex(const char *text, const char *search) { int position = -1; - char *ptr = strstr(text, search); + char *ptr = (char *)strstr(text, search); if (ptr != NULL) position = (int)(ptr - text); diff --git a/src/rtextures.c b/src/rtextures.c index a85467d8c..ddaee2939 100644 --- a/src/rtextures.c +++ b/src/rtextures.c @@ -1039,7 +1039,7 @@ Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float // We need to normalize the data from [-1..1] to [0..1] float np = (p + 1.0f)/2.0f; - int intensity = (int)(np*255.0f); + unsigned char intensity = (unsigned char)(np*255.0f); pixels[y*width + x] = (Color){ intensity, intensity, intensity, 255 }; } } @@ -1103,7 +1103,8 @@ Image GenImageCellular(int width, int height, int tileSize) int intensity = (int)(minDistance*256.0f/tileSize); if (intensity > 255) intensity = 255; - pixels[y*width + x] = (Color){ intensity, intensity, intensity, 255 }; + unsigned char intensityUC = (unsigned char)intensity; + pixels[y*width + x] = (Color){ intensityUC, intensityUC, intensityUC, 255 }; } } @@ -2405,7 +2406,7 @@ void ImageMipmaps(Image *image) image->data = temp; // Pointer to allocated memory point where store next mipmap level data - unsigned char *nextmip = image->data; + unsigned char *nextmip = (unsigned char *)image->data; mipWidth = image->width; mipHeight = image->height; diff --git a/src/utils.c b/src/utils.c index 5ccbc4fa9..123c7b0b9 100644 --- a/src/utils.c +++ b/src/utils.c @@ -374,7 +374,7 @@ char *LoadFileText(const char *fileName) // WARNING: \r\n is converted to \n on reading, so, // read bytes count gets reduced by the number of lines - if (count < size) text = RL_REALLOC(text, count + 1); + if (count < size) text = (char *)RL_REALLOC(text, count + 1); // Zero-terminate the string text[count] = '\0'; From 18e4d1d44fd27700b57f75722879e3a41557aafa Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Oct 2025 19:20:11 +0200 Subject: [PATCH 012/102] Reviewed formating --- src/platforms/rcore_desktop_glfw.c | 14 ++++++++------ src/platforms/rcore_desktop_win32.c | 2 +- src/raudio.c | 4 ++-- src/rlgl.h | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 0144f623d..729ca308c 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -56,12 +56,14 @@ // Support retrieving native window handlers #if defined(_WIN32) - #if !defined(HWND) && !defined(_MSVC_LANG) - #define HWND void* + #if !defined(HWND) && !defined(_MSVC_LANG) + #define HWND void* #elif !defined(HWND) && defined(_MSVC_LANG) - typedef struct HWND__ *HWND; + typedef struct HWND__ *HWND; #endif - #include "../external/win32_clipboard.h" + + #include "../external/win32_clipboard.h" // Clipboard image copy-paste + #define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h #include "GLFW/glfw3native.h" @@ -1030,10 +1032,10 @@ Image GetClipboardImage(void) int width = 0; int height = 0; - fileData = (void*)Win32GetClipboardImageData(&width, &height, &dataSize); + fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); - else image = LoadImageFromMemory(".bmp", (const unsigned char*)fileData, (int)dataSize); + else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, (int)dataSize); #else TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform"); #endif diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index b9acde0e8..3ccd4d3bd 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1486,7 +1486,7 @@ int InitPlatform(void) platform.hbitmap = CreateDIBSection( platform.hdcmem, &bmi, DIB_RGB_COLORS, - (void**)&platform.pixels, NULL, 0); + (void **)&platform.pixels, NULL, 0); SelectObject(platform.hdcmem, platform.hbitmap); diff --git a/src/raudio.c b/src/raudio.c index ca63b3aac..de2bf81b2 100644 --- a/src/raudio.c +++ b/src/raudio.c @@ -1587,7 +1587,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0)) { drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3)); - int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL); + int success = drmp3_init_memory(ctxMp3, (const void *)data, dataSize, NULL); if (success) { @@ -1631,7 +1631,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, #if defined(SUPPORT_FILEFORMAT_FLAC) else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0)) { - drflac *ctxFlac = drflac_open_memory((const void*)data, dataSize, NULL); + drflac *ctxFlac = drflac_open_memory((const void *)data, dataSize, NULL); if (ctxFlac != NULL) { diff --git a/src/rlgl.h b/src/rlgl.h index ecd3795a9..9cf8ebefb 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -3750,7 +3750,7 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format) #if defined(GRAPHICS_API_OPENGL_11_SOFTWARE) // Copy framebuffer pixel data to internal buffer -void rlCopyFramebuffer(int x, int y, int width, int height, int format, void* pixels) +void rlCopyFramebuffer(int x, int y, int width, int height, int format, void *pixels) { unsigned int glInternalFormat, glFormat, glType; rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType); // Get OpenGL texture format From 1f65a172743fe56dbce943cded3b208cdf626571 Mon Sep 17 00:00:00 2001 From: Maicon Santana Date: Wed, 15 Oct 2025 18:22:05 +0100 Subject: [PATCH 013/102] Set name as Const and remove not used variable (#5245) From af118599062a436190288b8909bb0e15d2210ea6 Mon Sep 17 00:00:00 2001 From: GideonSerf Date: Wed, 15 Oct 2025 19:25:01 +0200 Subject: [PATCH 014/102] [examples] Added `shapes_pie_chart` (#5227) * Added shapes_pie_chart example * Made the example colorful * Added some interactivity to the example * Revert top comment to the standard * Remove unused MAX_SLICES constant --------- Co-authored-by: Gideon Serfontein Co-authored-by: Ray --- examples/Makefile | 1 + examples/Makefile.Web | 4 + examples/examples_list.txt | 1 + examples/shapes/shapes_pie_chart.c | 224 +++++++ examples/shapes/shapes_pie_chart.png | Bin 0 -> 17457 bytes .../VS2022/examples/shapes_pie_chart.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 2 + 7 files changed, 801 insertions(+) create mode 100644 examples/shapes/shapes_pie_chart.c create mode 100644 examples/shapes/shapes_pie_chart.png create mode 100644 projects/VS2022/examples/shapes_pie_chart.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 6e2853edb..be6b4d52d 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -558,6 +558,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_recursive_tree \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index f1662a301..4ac55900f 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -558,6 +558,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_recursive_tree \ @@ -868,6 +869,9 @@ shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_pie_chart: shapes/shapes_pie_chart.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 81a61fb97..dc116ec75 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -72,6 +72,7 @@ shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joeche shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605 shapes;shapes_triangle_strip;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5 +shapes;shapes_pie_chart;★☆☆☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c new file mode 100644 index 000000000..68993ed01 --- /dev/null +++ b/examples/shapes/shapes_pie_chart.c @@ -0,0 +1,224 @@ +/******************************************************************************************* +* +* raylib [shapes] example - pie chart +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example contributed by Gideon Serfontein (@GideonSerf) 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) 2025 Gideon Serfontein (@GideonSerf) +* +********************************************************************************************/ + +#include "raylib.h" +#include +#include + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - interactive pie chart"); + + #define MAX_SLICES 10 + int sliceCount = 7; + float values[MAX_SLICES] = {300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f}; //initial slice values + char labels[MAX_SLICES][32]; + bool editingLabel[MAX_SLICES] = {false}; + + for (int i = 0; i < MAX_SLICES; i++) + snprintf(labels[i], 32, "Slice %i", i + 1); + + bool showValues = true; + bool showPercentages = false; + int hoveredSlice = -1; + Rectangle scrollPanelBounds = {0}; + Vector2 scrollContentOffset = {0}; + Rectangle view = {0}; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + //UI layout parameters + const int panelWidth = 270; + const int panelMargin = 5; + + // UI Panel top-left anchor + const Vector2 panelPos = { + (float)screenWidth - panelMargin - panelWidth, + (float)panelMargin + }; + + // UI Panel rectangle + const Rectangle panelRect = { + panelPos.x, panelPos.y, + (float)panelWidth, + (float)screenHeight - 2.0f*panelMargin + }; + + // Pie chart geometry + const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight }; + const Vector2 center = {canvas.width / 2.0f, canvas.height / 2.0f}; + const float radius = 205.0f; + + // Calculate total value for percentage calculations + float totalValue = 0.0f; + for (int i = 0; i < sliceCount; i++) + totalValue += values[i]; + + // Check for mouse hover over slices + hoveredSlice = -1; // Reset hovered slice + Vector2 mousePos = GetMousePosition(); + if (CheckCollisionPointRec(mousePos, canvas)) // Only check if mouse is inside the canvas + { + float dx = mousePos.x - center.x; + float dy = mousePos.y - center.y; + float distance = sqrtf(dx * dx + dy * dy); + + if (distance <= radius) // Inside the pie radius + { + float angle = atan2f(dy, dx) * RAD2DEG; + if (angle < 0) + angle += 360; + + float currentAngle = 0.0f; + for (int i = 0; i < sliceCount; i++) + { + float sweep = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f; + if (angle >= currentAngle && angle < (currentAngle + sweep)) + { + hoveredSlice = i; + break; + } + currentAngle += sweep; + } + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + + // Draw the pie chart on the canvas + //------------------------------------------------------------------------------ + float startAngle = 0.0f; + for (int i = 0; i < sliceCount; i++) + { + float sweepAngle = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f; + float midAngle = startAngle + sweepAngle / 2.0f; // Middle angle for label positioning + + Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f); + float currentRadius = radius; + + // Make the hovered slice pop out by adding 5 pixels to its radius + if (i == hoveredSlice) + currentRadius += 5.0f; + + // Draw the pie slice using raylib's DrawCircleSector function + DrawCircleSector(center, currentRadius, startAngle, startAngle + sweepAngle, 120, color); + + // Draw the label for the current slice + if (values[i] > 0) + { + char labelText[64]; + if (showValues && showPercentages) + snprintf(labelText, 64, "%.1f (%.0f%%)", values[i], (values[i] / totalValue) * 100.0f); + else if (showValues) + snprintf(labelText, 64, "%.1f", values[i]); + else if (showPercentages) + snprintf(labelText, 64, "%.0f%%", (values[i] / totalValue) * 100.0f); + else + labelText[0] = '\0'; + + Vector2 textSize = MeasureTextEx(GetFontDefault(), labelText, 18, 1); + float labelRadius = radius * 0.7f; + Vector2 labelPos = { + center.x + cosf(midAngle * DEG2RAD) * labelRadius - textSize.x / 2, + center.y + sinf(midAngle * DEG2RAD) * labelRadius - textSize.y / 2}; + DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 18, WHITE); + } + + startAngle += sweepAngle; + } + //------------------------------------------------------------------------------ + + // UI control panel + //------------------------------------------------------------------------------ + DrawRectangleRec(panelRect, Fade(LIGHTGRAY, 0.5f)); + DrawRectangleLinesEx(panelRect, 1.0f, GRAY); + + int currentY = (int)panelPos.y + 12; // Start a bit lower for margin + + GuiSpinner((Rectangle){ panelPos.x + 95, (float)currentY, 125, 25 }, "Slices ", &sliceCount, 1, MAX_SLICES, false); + currentY += 40; + + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Values", &showValues); + currentY += 30; + + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Percentages", &showPercentages); + currentY += 40; + + GuiLine((Rectangle){ panelPos.x + 10, (float)currentY, panelRect.width - 20, 1 }, NULL); + currentY += 20; + + // Scrollable area for slice editors + scrollPanelBounds = (Rectangle){ panelPos.x+panelMargin, (float)currentY, panelRect.width-panelMargin*2, panelRect.y + panelRect.height - currentY - panelMargin }; + int contentHeight = sliceCount * 35; + + GuiScrollPanel(scrollPanelBounds, NULL, + (Rectangle){ 0, 0, panelRect.width - 20, (float)contentHeight }, + &scrollContentOffset, &view); + + const float contentX = view.x + scrollContentOffset.x; // left of content + const float contentY = view.y + scrollContentOffset.y; // top of content + + BeginScissorMode((int)view.x, (int)view.y, (int)view.width, (int)view.height); + for (int i = 0; i < sliceCount; i++) + { + const int rowY = (int)(contentY + 5 + i * 35); + + // Color indicator + Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f); + DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color); + + // Label textbox + if (GuiTextBox((Rectangle){contentX + 45, (float)rowY, 75, 30}, labels[i], 32, editingLabel[i])) + editingLabel[i] = !editingLabel[i]; + + GuiSliderBar((Rectangle){contentX + 130, (float)rowY, 110, 30}, + NULL, NULL, &values[i], 0.0f, 1000.0f); + } + EndScissorMode(); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_pie_chart.png b/examples/shapes/shapes_pie_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..bad7960f476c0d66e32df5d38b7aded5a81b5a75 GIT binary patch literal 17457 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%10|NtNage(c!@6@aFBupZ zSkfJR9T^xl_H+M9WMyDr;4JWnEM{QfI}E~%$MaXDFfceD^K@|xsfc@f*LIWY$*{M- zFSEU1I* z{NP|^X<)}=oXzv=@%4MJ#NJP5FMm7rpJYb|)W*ubw#zsB?z`_due-E&*QC1l9Z)+a zJm2H|a{m86&sUnfc_&n}eo=Ml@tH1ejEq9Rp2yeip8HRZ;Y~Bsr#ZV1z0*7RU29i( z`5ey_5rG6{sb9*M{`)dqb7!nP7n@i<{XwwE% z!}+YdPkuOl=R2@hL*e{RZB&cJ7Pu~UYc_vX($5&vj%mPyv?whbla#~m=a~-3NOGUJ zetr5&+wz#@-_Mn(z1dgiZ?z2O5z`_y<>v)U(uE{hS$52r*5RMA;8^;XH4JkmZ*6#S z%?tq0r}>QrfGLC2S;D$-Yr$&-n34%ESzKCF7{tvCzq^`N-z4B z1M!}06vMn_jS}ZC+G{(6Npg3z9ozo+&hP76zos9%>T%=h`O1r?UWeat9Sr~Ou)l87 zyU_PO=jK3scwoW8dR3{Wjck97SyCo#Y*_Os=f>4amD)JDS)W)gPW=9K@`l~sANF>=yLw_~#kt3>=Rs-a(&dKzR=m3-rvHm%E^}q9JeP5! zR+@K@R9QLazVM5Cr7S03++1!qk^HRu9^{M@#vBa7?Z8c$%R z#)I2Tw!C*atdn%vez${($b{#2M4>K%L|cNj)V1;@jAGRn>`yz0V3C)Wx>UaGplJ0) z``ZUzX(*hpY`?TxW`BQO{+}h)rK*4L2?ja{%xn9sW3na5{#UwegedD1ODVtf-LHSY zd9ZHpC3|L&f@y4@a!l4F#s5l|kKlzA0S_|-&U-m)eOqqNeLxFRW^gz&SCmQlO>F;{ z!{EOdT(l%qO6~dB+!pj?vAy)ekkq6?S>8n_JiA+`|Knkn+su7p{r-PeQ|s&+(gPg~ z=CY;4csFZ&x@c55?Vk?w;&mDdR%O@DoM$p%XJrY_v^ZvKGC_%7S8)EN`I!kvLRp`@ ze*Iec_<5!cd|VvME;#g5XKJ|0MJc3RoL{)06P`)e{qiCvd>^UL#A0nQNj zxtnl2mXz|D*euqj{o=e$!a|7qM0gKWOk)dvK91{8CPwEUGH}M`+NRo*8FH` z`MK;$iy9929@d|?{Gmwo<)Q-dS}}%vLGF&e-ZQm}zU|!l@nWTd5*J5|$&Vynsep~< zx@_f_(wRPNie?PlTevsgzBnbu{`Rk$zdaMHr`FX!;1m(yxp<)aYlg?sd0PZ*T;~g( z&`o08xaWDv+Y>wf1<#eWKleH++c#S#f|ZpeR;py98tdm2BZ*(?OZc+$B2OG3Aun%oLP?ExU57t&oyf1AgZCi0K*LGr(WMVvH$Y{{d8s$u z;K-Xahb`jBGDb7zy(M*OdrRufc)tj~G-j{fwW{Ha!RO5kXB-(leGY3sy38=UG0w_< zG6=K%Jn`jb^WT_2hqO!Q*+1xTc?3ztY-H!%XsUc&^!2$va#>N?UyQ$OIulQF?Tj@&5K%*QEaP>|L|*`qKHu ze{5u}>)QJ2y$=7@`x4nw3u!4#y11e1Z^n$TR&B4s4%ltZOW9*?zU$a5`@XAnvC;W2 z&(2@Cu-5#S&mlR8Z#y#rj?Oc=P$lbJs+}-D(%k6YZ0XqKv+~E+oQ}F~wCkKR^Y6Yd zH(P!{RC{K49NmXob>0-VuXA4-b8Una6hapoy7p$S$jyx1`}2Eg%<}p7XG!n;BKNvZ zHvepN^1RBYvG*4-+A`OMDe8fXkrU5M<|Nfi6K$I2!{-eo7853fC*vBGX$_T9^~R!i<&zWvy&?Z?&>zP?nw z=J&Zv0rPt8b_?)>ONf+UDUXTWY%%>818QTg?^IR5qz;W)iw8%Ib3b+^nCG z49^xcowl>ax~0?4 zonJEjT(rrDcV7B)=X>hU{eIy>@B1&3?OP!+WcI=RXN7T-#=3=Yl}WNv+Y&FQ%U**N zpPcWae{uvkxvkT_HutCPl`Yp^q`ye*-K+O^&g17VZ+tW^`QzcNe{F%HbndS+hi5@j zNu%gdWd}~lo$DgXpM4Lw9JP4SFXxn&m4Zt2J;p- zO4a?+Ibx+GCUCmi?|NU)Yx}8n>y7URKcCun-EO&A-paLK`J)7g0v5CiHn_9Ib-iurvPxt=&>;Hbozu>FK z?ia5r_0Nupe4YI`-QIcYF_6;~To+m#=2+>Ufyi5{dm&*2$|=3;t}FDUXLKA(|8leA zd7#6o`c=0ovfr)xc$Mwi3LmsG3AqF+*`>Bz zU5*y=(aG0#l)kjRR%i4|d6n3~S-{Vs0N%p~LxD3@mB^g6h2;V#h) z=hsL}zCYW$ZsW7;^M$Ac$b>R{_*Tp>FxqR7nQ1KY~ zdDpv&m$UArYw#Z1(ax3{<34}x4tYqqk?88VW0qiC;BrVV*`8r=?5l~wz5LGe!ti( z@_px`hBHg%^FN3bnZPRA`he4If~$|zghE-6hwZ!z=ig*yIdD%ypb?v3cSD=y@P6qkp)3glY_i#F=56+wOY9oY!^U=?2KuFR{b!JNsLcwF&w-MO;;%0<^q$W+adg+0o83R5R%trb zl(;=O8fD_}*oJpU#C*GELvgULo-n#r+;0`E+Q`Ry(Zao1_tAxP!)K6olg$E-ch-hY z`qvgXN=a>zofSxVdSnKZg zFW{Zc7W&3}{@o7{FT||ixU)f0QS$o51-+BlLf-fyWR`H;%rI^;TDLG!T9tRjjrn$m zA41xzJ3Rz9Tug6CJ+nMf`hKQ?E8j1kc1ZR5gvoWoF$-mbWINuwKOCJki!P>H9)lz( zy?~ai9}e1m_sG zx4nO3(xRkayDXUp949G@lpK=zlpP)$OC8vJS)l9Amz#Zdkbrk_EjVW5)^V&->VWa( z51cPH%hp2T-m~jK&(9u(-p?i-=}R99S6ocDxdjQ_$s&o8*A1FX&RtZPH?hs{f$#i} z8IaKN31~@)In8nT!)1ecy=;CCFE`7TLQLcAYUp__2}&y`HecMpsZo1vF~m2Y7Ai?R zwsTu?%!2pH%!~^xSzl)IOM@N##MxEj*x#OlUOV2WGc!)0%19hD?rG??<9#NXao|X0 z)yqG!>;C=wb*8-+91@=zl~^7}x*c$v-S+uz=8hxjUoQQ$zVq?#*PH!95VM(G8IFDK znb2#+`(pRygr6-FUw4(J*YTUKHT@;29G*S5uI}~k>&NVup0As-hUwG)KkNT9G}yoR z+{jcEBv`YNPdVf8GRE3;DXsZNMX?*-oq4}-*;Y6EJpGz)Iu-Ub4={L!(9|QOP?*F`ZYgK<-x}Ed! z^b6$-`xZAatXSCK6T}j`<}Am(AD)MQ<(YWc<(jDUughLp>y}#+^8VlBn*6o*7GIxv z{=&z|FR=~tH53@KG!!O_Fp9r6ZZfaCaA2P_??iv;oi?xC?7qKwzi`?1XBPHFFaQ3E zv#ccr^S-lh{@KF1CzpPI-CVLJ z?a61mrSDn(YzSuj`Sp6dp~v@iZttCWs`}Cc9n>_ObdwC3D$1m8l`nc&SbCh{F4yI? zJ13TI{dn)ri&>9rvfsXld7E{&ShQCCLHk{t`l5i+yu^hHUH)_F>x#8xvX>5CcdjCi|OOTsEu zaCqCUD!Y2^<&T_Sc?V2cpKOn>o9Si0KP~OUt(i!+H!5vO(s$E1@8Vn&A|+C&ySL;Y zpMPzAt$T_)*sE}>90Vga$}7)EU+8G3#oM`KTAWpV`|^GJ_bG2$-0dV9$Vg*<2vE#>TvX54=9a)zL;Ua@@~QVt}_}6KP$d>rUjF+Eoi-)^oZ_xca#z-0x-k&0)gBRDQYKElgy>`~BDU zYrgD_jw;sP@NH!q+$AE8B9)R0Yt^ORDPJ()xZ`_YGBQ;|VcPdQg>(B}KHsuWZfC2c&_X1eUVM(pDGTUTAIty+K8slXhT zzK*Qqn17&K@Lu@>#`;t#hDP<5yOou>JZjJEN^ePjEA00D<=!yvgLh357M}$rX@TWR z6-@bV4fh+_{)T2Uu*_TXzOScDU*XqwvE%#qUWmVbZTm6ZwL3*4eup?Sb{>anDPeMV zYv}iD{?}#lhtdCXxx3qLae*l|zg=KT+LdycOx-5*dmRQV(Y{dbVJ0%621P{*ldjv0 zeviZdvP`}(uEwS!fyvfwLBAXGe=m~{jM^8mm=VLI+!G+*+4gU0#slWCMeir%phkUj zR{&>)#6deD-hbK`Hn6YpxUV`hz~R%!H^Qtca_4`33vgf)Z4~-o)Kn`X^>6+%MgEAX z`@D@7qNGwDtwSmWZG!KVFED*D;jKKd>PzgTlcKCoG>x0DpF{X)f}`sM7Q4ijKT|Uq zD<-koB&7b*JK2JgnvE84^dI1HyAVHhT7!D#0p_sf@2BXXI+(fZ0mqr7mcOEzoE2Sc z)(T9u%TpY|xoiDa(8vqK%_0j0XPo5tqkYM!z?`?#LFAX;$)xQ}O@_P5O{?USE)?5z zGZ`)5=sA$%_8`7jtZ8@V3g$%@%Du#_MFkj&10C2z5(RfO3H}OS)cU|r>P3Ucm${Qz zSy>!-S(hy4=sYmB=fQq1UDonT4(u+A-%sO#l-aVb4lM5yL>iW7YVPP}vs6&3-JasW z$QaOsScFS47h!R0~K+N=MKDn+EuZ2kZ$W|u7FXzYBs^mBQ| zuiy6PG+4?nPbv`Q%{#yc*8nR(Je&m?gfDwPfB)gj_xPqju6IjZA96|EYKVPdomP&L zW+${M{juzg314IVxq3zB+KcBUc1FGa@;UncezSRPfqd^4q#`tii%hux@9p%JUp{B2 zv8|t5i71VDU0)PSA@#Wpi?&{S`F#7n`dk~)#R_*ExexnD-DsGL&GrwLy=_mf?RtFY z#jc6qI_ut^t$yz>uFp=M_tT`OslZg1cXLJrbJ^neGwueWq;jpU1?7h_Jo46BpX*%* z>9V~%8~r+K`nqh%*y&AyLhF_sO%&tJKG63ib~9=L>)|T+$xnj!?hKi<3Z zqUqks?AW)LN_7{%zGTpKD0GX(nFWfxH>U2(E^`B?Rap78QiJIpr}Fi}x%bu=FMjO? z?nhUBo>#iJGWK=k{H8#$bqk&*vhijfSclEpcYYE(`(A&kn=2g)8SlD0`}>;LXJ1F1 z|7Fs1$YA!gcK=KV=CWn)XU#<^&UyaYZMG{{%buSFt2l!KS#}FYDgLxDufBVtB0sOh zH@`0BZsEGJt?wESYVa9nc3OBJmfT=nd;N`$GvmdL6L&_w`ym&1&F*S|!=sPj^t6bh zM170Xr^38%u(1DgV%K9(d!d7**KVo^4CgBUS41QSir4vhGX{;NvSgpJYQlrZ{}e=@@by+y32-t=Ulsf zyl`puytKE$ys$z`t4pEWNn1t!dD?ndWNyFK+w=1J-a?5UrjMGs!s!_X%tjZ=&z>vO zR}fpB6Omlif5~+1?{K4C{_nR+y;*!AVO}e^aujv#uugokt7z`?d9&`#y0>TRx>EnQ ztJYpF43SWMBpju-$7Bj)!f9e${Jbd+X1~tey!wvS<^Q!uKemhidVTBHwH=pCx0d>ELaGwm zly*Ff{!zb*!RGJZ?FmyljkknUWJoY?x>$a0U75au22##xQ`*9~+t90Zx>&cM)RBgs zFLO6*gY!NtD|am9$Ue~56ZCN5)1($QLj~p9=Wn`DO5h}oCaDeDiz9k26wq|u1c$U==WdF! zs>q+W3xuYXBLOYO3e1aBwq%@Kaq$Cd%JTPfVo|drkE;RmCW9`w?rFT;ZTbqSFpdW#+-`bVSppVA8&Vt7pdU_5m+)@x=*IAL{mXM)7*Elz4zKBzQ~*hSv-MtK^GI#j~CYI;k!izWSvifn%TeZ&pdDo z+|)J9IKUL}nScNP&-wfR{JX8s;P%owJsez=e~DWCzx88=$%6Oiz)cxv$xRG3-}(Pv zmuG!)|6jY{HijB3v6Xs*sX#~e_@|F+8vcCNjkMZQGlR87h$#eQ zUAV}E$HnPvfB(!vk5ryS2eZ_N0l$>=xj0-|3_yy(Zi6?ToF$Jn@SK_yxLE(=^hFgK z${mc7*c6>_2W$R|aT!t+WGMJULyN^izdbCZ1HMvFbLc?5;t9FY|SifHXa`n3% ze(!Ca_n%*LelBv6Cvl2_-6dG8!~bRX?Vu^#{K_jBtuK|ITW2I9AS*p{_S3%i4^xo} zHlEZO%!@R-5A*!Gv`*8jb-LiShP$9>hP0^nzUcklvu^ifq!zN_l!bf|k&zNdR> zfs|H9lBV)z`@9d_bw3Fg}u^ZfbI}*TVn;@F%xMR}3HSQv+kAmGA zn3X{3R72sb;cL0|o4?0qmdwAGZF<3dF=K5xxXmJQ>H@pXN*%WHi_^b$EOI!L!~$wO zJ%5w+ooP{hcHy7f+7UL;3U`ij)E>|R*O16PI1g7z1;+J857zs{pP8@Kb?|P_2X-6Z`=-{YoyCwT zi9!;gZNE9b9JO%<4bQSTJn;Or?&eJ_P4O z1u}#swm3h?0y!^_l_k04ebyJdBMY8ah_NnN#54cIN}jj7FDxpUs`O+1F^uy>7U32mM(#M;@ z%~JseQ;`X6Mq8A&8TF(uKKek`(9_wPw#zMlYdtI zi|ppzbGbVH&29)-ULC&pyCR$I@y#G_H@MoQa-8?+J{a2-Am1yfrfk9XDr|=xWM*{J zGP8BxBd2d&ms)Z+@>k!@yLqfG#{)jSxtzWBU%A=_GjO-a>Xbvb#HkN+=T2+dExOQ7 zNjYTQ8;KRs4}YBjH`z|iy0zn8dhE4b(=L{#zW{YnK&cSaZ`kyM%cSJ7I@FMa?$W6X zrR_5$E1U$MDH}6AyBu}BFz)?jXzO>Psq*xDi@(3B=q=ydzAxHn0ZQ|sWQwBrYfWbJ zeV2_sv?v{MPj5M+zIEN>J@=MF8^FrhZhCv&-(USG^}dQ9+=T*-62ThGFEtM9T?=T- zxv_=AW+}&q-3EuAY4tVk5?u$GXsNswk@fv0WPZjN)JM|h>ae?Sw{(8Iv2n%QGlYsE`REM|R>>6&rBSI}mD35xDT-(Oz8R*~zQ|4#Uq-^nJFHkQ!>o+CTrelBY0 zZ~HGQ(pVer#!-97Fkt(kuQNg22g~zP-S?KqM?c%F+`E?kV%B3T+5c1a1#dzPejW{Hqi0(2Tt9l) z{!bNAtSxs_X!X^fJ0FBy?`uY)`?FE9c#1xAjUV&>tgeQ6t%5!u=f+vtgJy@i_XTgd zvA3b7wsz*d;^U=N?Y_jX(={9DC} z)aytIkX&^!-0n@GEblLEZKldFw}hi{Ut%YDwlO7Do|nD;az>rs>(`HWTr&0FjMS!X zK2^XQ{j=e?t;v)1Yd9X=lsqU}eWBb_ZMV2Ucc|GK!@ce=rB1)tWesk~xBVB*cyY`h zTvb_2NtCvq%3pTJo%!FZE`~m(9ZGh!?J3TTEBhnASIph}-V0nIKCEYz+VycVxc|VH z`r_QWni-Glq~0lO95SynYSKx%RPJH6TU_98bob-?aWB?qzm9%vyZH6H6r_q?<`l!c z(4PXwi%ssh2eRbXq_adF0S(`vHTn5c1YGSSU(`L!nmki`X1vgzxZ;4&weqUA+wf#Ql)C0NLpAN@WgGo1Wr|;!(?$JioLx zo3$TZez31w$>p)Jo5Hc$FR>FPQ93D4mKc3mzkp}$jpnv*b43`XiX}iZPvx#@;I`w39U{5bg|!90@jv{luj@chw!}io z&o8W%tidBiC)iIl6|@>nP~zu(wOgynXkBVcdX3+G!JB~&3|9gi>_WuaB2O7~#h5I4 zzmDVNj%k7m3g>}_xETZ78Gi;u%Gd?A1w2{GSX=JuaLl&HfY%;0cFwe*kLlCGO)hf+ z+x(v_duY?FB=I;7H0x7qp0J*2(SJ3CD=!gUof9mn3nc>E{2sVASBkkR9Q)go&})Y> z6@WAlGodW)Z@aqumLn}^@)*p zhC_E-{-1!Bm^J4)URqzqP@%{>v%%HbyiV(o?jwUkzw*A!a0wmY@a3li zL9=Q_b6Wl`7% znyI*XKmM>;j_VB97`KjoulZkBoDOh+Edb7}t(6Ji^(+%yMni(yXTd_@=P#CiE}!x9 zuW8ESbsQTz&T@Pf1kFP37ROTFf>we)SP$-gPTNc(Dn{ ztPMAs1z#<`0Gc${&$Nkp=b zV8ljssA|WnzkErfRGq7XE1#QSMH6^h9NB)o1qZ)qE@lL;KSOdnWHzwM#N+WC zr5Q@%i$(5u&VMR_n$5&7HvDS2$N*mHW)=>g1nfI^b=@^vTd5_5eu5qo`vZC2EjVBB z16;favqF=stH}bpL=y-3>s#NgM2f6ycTUWxyDJ?owWu&o&~4&$(CF^@f*&z~4)ctl z%|w{DFD2VDXllZ+~l=~Hq;=QYv+WvtJ*y=;p;x%3BDX% zJV$=#7rD^gS+7g}cpNsi3ug&9puubWa=npi>`XbqTJ^)-3$t_D1+nC{S zY-?8mXO9sV`_so!BH(@yD`*vq)P%ydN+C>gZXXxa#H26BtYer=t|+nb9^VlssL^Pw zp|JhN+J+YrUh`@}-H>xE*PemKQ%@+F+)2un>M5MBvD&}f0o=}kDAapP!}iNNDHDJAzUhdveNJ^8d|^FDv@>dev@`{@1aVqs-U{9LU5>syd;7JQw%|f&zf$e9M^dQH zXU+U@RLX?qv89wob(G>x)AFZQ?``)Y%~OOe0$bkTT$qit1|e+W`G}ZqaC(MKL2NSMJyg-g7Qe>vaO&w3Pb05iioU+9WNqpEzUa@& z)9EeW**BKX%&N9iFSIBb#6rz2v*Tiqv z`@81W^Qb;h5HHRO&z;-1-eLa29pbD@?9%RDUi|vYYtbIiY)0E((M*o>XFy}Z6B0}` zlI?hRMoecr#{SLqtONH-Rw(XrKxFG`lFaOBS`}a@z%gxT;Z{r*SJ|SkDnJ!)EsRXZ!w_&VJdnAdPk{6g*JT8{X z5o`uES;1>4k<+Zu47Q9p%NL3jW-z$M{pvZg8MVjJmWEW>WS89Ur&w?!OTc2MLuXu+=&q>hE=?3*2IIa@LtTyv!SHrm&+CF!Di{A|XF zHeb-v{DQ8%pasX^N%-a0qj+~j%m()~r7vyheQ&ZOZTa+b_Y;qOzuwSQ`_h;{`_|fq zgdU{nfgCSq^SVn9X3Yf^c9Hkvo3*|zK5w-qdpQ$Rf*#k2V|88#aYFWrAA28 zwqm?%Z#3Io7GMU~J1UI4k0dh#{)T`oih7;(eZ{SqT+qe?J8&+0x`WCzWAZ&#+RFU3b9PQd%8GRib(~eOYA(i=JNZ? zvmgtJB0jJ6et-QpcsW&+$pIz3+BU^$*rwxE7C)>hm-0)O#H0O)l3HzK_;_*UfTs;H1%%b zLNUV^##|d?10DYToPK}VrSt32df+O{57vrH;W1+AL$U13>B5hoZChw1yny5V#Y};{ zw+$WoW74lxf_4yCp6idP>R%PRwbbg}QbzIDm(qp4K~{{x#sUw@n;dapswh$mDofV= z_$O7gQLR=iQ644R2>gkcdZv6ypvw-l8Y{e}o_AM7zg_bNad3FUCPq2-U38G|WD9U$ z*1xv!yxbc|Qwvr#H8p`Ib8DESsy4FKK1=W?Q2iWO^02N{%BB&#wBIg!!+J+_GM<{9JKK(3s>%g zb4_BHY(WdfYr_=uQKQB0a#Ddf?{tU$wv-s>`GO~UQJM@*{h5wCCb4-Zw6LX~S$dx3 zK`W}X<`#_@*Jf1%FK6Rt7t$F&psu|*Xc8rscG-cmBBS8gbI{H-)FCW`xnk{-CO%AY zQu7Mu{X4@fhUzlCg{+T)rPLVpK`XcGuQkrn<~k9KwvuH>&$N!sCLT=bnKRn@|Mf7V z7U%*oe%!6?Y#tAUrB)ca)h}xlL`}GNoVt%{@J=|OZW6KBzkXU{AXpk{;E84X#iEOg z9}51M(w4pD<#~e#8>1NyN+7KoI{0==Mudq4)8>p5Zl3jNjmFTK=?8*Q7E{{X62y3K z|M061YupT3z*I3sjQh_Akz>eb5AtJ8{UlGaj64QqlaWF&omr-@tQ<{oNu) z8|}Z6ENPIXrwN);B8}P^0_Q#Izct(}(^5d6l1}iHl4zW1(v!Z(KKnpunYMye+obgQ zaoJz@8#h8`+MAYU7OX$WGqt?CxZQy{sRKCRC`M_M%(vZWwS*4(@?d#kZ=XpM~Xmg#&-~Z=!$giKKXln&p zmLv*&xO8D3_uojyd8k#hV}_I#BR}u^i7(HyeK0{y3ELJN6p~n|Xs7fyk|7MT6b)WN zg_$HU=}J9QzG(mZKo+X2ZcJkHUEtRI_tls4RvWa?j9iu|93b@}d};l*#;XLD?lg&* zlrZH>eFBIk;ztTlIbdXD#uZ1x$XDvrAW|k~Z6#1DUxMTLenJi@+us1+2lrL|z zlL8kq4gVJ|6sgQm+|m6{lBLWEJYxRkh1K6GR`8HHV{N(Ai^brjL@Wjw4oB~8k%;m9 zzlL%5Ez|-AqgBb0abZDMZD!yM-~Ty`yKnDpSnvcfAk5HgvLQ)7N+Ruoy|aTFI0M0F z^&hbCuJ7>MwzgW=yHS=UZ)iH)wsF8iZ*W^u-tq5NNq?(6UJ0BQ$_eC%-WuEaIb9D>H1_s_k zJNoCbHdvw=w#Y=|aq+I>4C|m{G|=`VBhy8PUaPy-4Bx@kI&#zS0Gmlo`l4#a1YWd3 zX@P`dsT+`E4z>p~G8%}pvK){%`EuW}o}b~HBY4V_k%8edWRRJG;XnzvFE7BrU;vpy zWnp0Ofy|7OrEDu`X9s9J7IZ>H1S<<@?K=Yl+QAV0S&To||Npf-rM>%q&ffp??^WA>8VdUB_j6YMoqFQ+|JZA<{}*%oFVg`T xlfGxyk=4O_b{$=vyyxGu$NK*s>Hm8n`=7mY>m8>sZ=NL}HJ+}1F6*2UngG-JRxkhn literal 0 HcmV?d00001 diff --git a/projects/VS2022/examples/shapes_pie_chart.vcxproj b/projects/VS2022/examples/shapes_pie_chart.vcxproj new file mode 100644 index 000000000..058a9b577 --- /dev/null +++ b/projects/VS2022/examples/shapes_pie_chart.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + shapes_pie_chart + 10.0 + shapes_pie_chart + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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) + /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 + 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)\ + + + + + 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 + + + + + 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 f72cd64a9..9051f9200 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -373,6 +373,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "ex EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_pie_chart", "examples\shapes_pie_chart.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 From d2acf0677953a73b73a16c097dff123bd5ca3c38 Mon Sep 17 00:00:00 2001 From: Hugo Date: Wed, 15 Oct 2025 19:27:42 +0200 Subject: [PATCH 015/102] [examples] Added `core_directory_files` (#5230) * ADDED: example: `core_directory_files` * Follow raylib's conventions * Rework `core_directory_files` example * Removed alternating colors & text on directory * Update screenshot --------- Co-authored-by: Ray --- examples/Makefile | 1 + examples/Makefile.Web | 4 + examples/README.md | 7 +- examples/core/core_directory_files.c | 94 +++ examples/core/core_directory_files.png | Bin 0 -> 2280 bytes examples/examples_list.txt | 1 + .../examples/core_directory_files.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 429 ++++++------- tools/rexm/examples_report.md | 3 +- 9 files changed, 903 insertions(+), 205 deletions(-) create mode 100644 examples/core/core_directory_files.c create mode 100644 examples/core/core_directory_files.png create mode 100644 projects/VS2022/examples/core_directory_files.vcxproj diff --git a/examples/Makefile b/examples/Makefile index be6b4d52d..8b5faf634 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -515,6 +515,7 @@ CORE = \ core/core_custom_frame_control \ core/core_custom_logging \ core/core_delta_time \ + core/core_directory_files \ core/core_drop_files \ core/core_high_dpi \ core/core_input_actions \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 4ac55900f..510725b6e 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -515,6 +515,7 @@ CORE = \ core/core_custom_frame_control \ core/core_custom_logging \ core/core_delta_time \ + core/core_directory_files \ core/core_drop_files \ core/core_high_dpi \ core/core_input_actions \ @@ -742,6 +743,9 @@ core/core_custom_logging: core/core_custom_logging.c core/core_delta_time: core/core_delta_time.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_directory_files: core/core_directory_files.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + core/core_drop_files: core/core_drop_files.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 441c5a368..3468ff34a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 175] +## EXAMPLES COLLECTION [TOTAL: 176] -### category: core [40] +### category: core [41] Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. @@ -65,6 +65,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_render_texture](core/core_render_texture.c) | core_render_texture | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | +| [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | ### category: shapes [26] @@ -148,7 +149,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat | [text_writing_anim](text/text_writing_anim.c) | text_writing_anim | ⭐⭐☆☆ | 1.4 | 1.4 | [Ramon Santamaria](https://github.com/raysan5) | | [text_rectangle_bounds](text/text_rectangle_bounds.c) | text_rectangle_bounds | ⭐⭐⭐⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | | [text_unicode_emojis](text/text_unicode_emojis.c) | text_unicode_emojis | ⭐⭐⭐⭐️ | 2.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | -| [text_unicode_ranges](text/text_unicode_ranges.c) | text_unicode_ranges | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Vlad Adrian](https://github.com/demizdor) | +| [text_unicode_ranges](text/text_unicode_ranges.c) | text_unicode_ranges | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Vadim Gunko](https://github.com/GuvaCode) | | [text_3d_drawing](text/text_3d_drawing.c) | text_3d_drawing | ⭐⭐⭐⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [text_inline_styling](text/text_inline_styling.c) | text_inline_styling | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | diff --git a/examples/core/core_directory_files.c b/examples/core/core_directory_files.c new file mode 100644 index 000000000..27764315b --- /dev/null +++ b/examples/core/core_directory_files.c @@ -0,0 +1,94 @@ +/******************************************************************************************* +* +* raylib [core] example - directory files +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* +* Example contributed by Hugo ARNAL (@hugoarnal) 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) 2025 Hugo ARNAL (@hugoarnal) +* +********************************************************************************************/ + +#include "raylib.h" +#include // Required for: strcpy() + +#define MAX_FILEPATH_SIZE 2048 + +#define RAYGUI_IMPLEMENTATION +#include "../shapes/raygui.h" // Required for GUI controls + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - directory files"); + + char directory[MAX_FILEPATH_SIZE] = { 0 }; + strcpy(directory, GetWorkingDirectory()); + FilePathList files = LoadDirectoryFiles(directory); + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + + DrawText(directory, 100, 40, 20, DARKGRAY); + + if (GuiButton((Rectangle){40.0f, 40.0f, 20, 20}, "<")) + { + strcpy(directory, GetPrevDirectoryPath(directory)); + UnloadDirectoryFiles(files); + files = LoadDirectoryFiles(directory); + } + + for (int i = 0; i < (int)files.count; i++) + { + Color color = Fade(LIGHTGRAY, 0.3f); + + if (!IsPathFile(files.paths[i])) + { + if (GuiButton((Rectangle){0.0f, 85.0f + 40.0f*(float)i, screenWidth, 40}, "")) + { + strcpy(directory, files.paths[i]); + UnloadDirectoryFiles(files); + files = LoadDirectoryFiles(directory); + } + } + DrawRectangle(0, 85 + 40*i, screenWidth, 40, color); + + DrawText(GetFileName(files.paths[i]), 120, 100 + 40*i, 10, GRAY); + } + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadDirectoryFiles(files); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/core/core_directory_files.png b/examples/core/core_directory_files.png new file mode 100644 index 0000000000000000000000000000000000000000..285e1745f5531fab094280af76ac32d02915f3fb GIT binary patch literal 2280 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8Xa%)r3#)OW*g1_lPk;vjb?#+xT~>KPaq zI14-?iy0WWg+Z8+Vb&Z81_lO+0G|-ouV245H#eU=c`_g%AR{B=#fukBO-(aq%qZZ| zwPIl4$n2q=B_v;=e@2~m&Jyl@FR>xhjdkPL8 znmRe!?(TiInT996uHg|Xzmd$b{^O#*s_dA{{ z)c;SOpdG>U>H7Xe%M&jJM9RM5-2e)%I{2?M*B? zF_V2}u8Fq_9RAnoJ~>gp?SlL~Kj|~`Pw%^*@#pT#X(waP&Szc! z@A2RN5-e$7>tp8p{ITFubo-pyR(5j}1!frici6f|y#DuuZ zH>MF0T|OHXN^j`bPg-_6sgk+()Y=LB-^#fbtv|u_Nnlo11^2^%o=0i^1pNab~;PdjbkO^nE9oc(A!DOc6yh9)J zK5f(ex*;z-Z9-mR&Y^9!%lDSdd~%xqlHMedBcef0brbS(zf3W z!U_NLn+xhNcl*E6u{+&_FW<~K!?`N=*VlIuPY#|?u&8vL*SFs+v3d{p?D?5I*9*VK z?9_hpuA=--OT2q~A@@nXO`P`0Q|yjT)>aAr$JH5sGI5hrQ~Y-o?`M`OIlqfNW`&lw zrhG0XBA=dHc^R68KQ1}wwK(lktL#FD1K!EEkxG9++*LJ;uAZ}E`9pYGimh&u8%T7UJI`)uImZnVS21x zir;U3b78JfFBO}gdJq~cSR>76@ICr6*} z@zs~R{(bw#{QYI~>SIdAk&e6e-z(+1bY%bc(2U<(cJH(+S$gaB<*RQ~ZE8Y4Hb2t+ zYWFw7YQ^0RcNF*!b4fOpG?v{By6GEsVqNc~Z*@FE;U3aUqT^csDcpC>n^5&Xt#yfL zLB^w*O6w-Pn{1-EcACMRef)>rrBc=%;Ob0os+IWu?u$&&TmR?1T0PtEhrc{=ZSPyI zzn=R#mCkQEXBRrl?)|SnSzozWI@Mc>zvoOaty#)PrK;wP>a#1qtLy4RZ*7xSTRH3U zQZ+rp<#un;$-b2N&3V)Q%*y{WE#oZlm z7gpPUao$~+WBV_{X4TzIhl*c)R(Q;ndALOSo8zS$RkN;Kjd^JKb-VVG`&zxru0Q5_ zxo?NFRa@q|4|9H%MA_cqU;JWuvB&pmd~un{`>&jo7M~UT{pIB-@mayOg`oah&3Ou`OjV?{wHhs TaxWDI1_lOCS3j3^P6 + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + core_directory_files + 10.0 + core_directory_files + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + 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) + /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 + 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)\ + + + + + 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 + + + + + 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 9051f9200..881c489ba 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -375,6 +375,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{02EA681E-C7D EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_pie_chart", "examples\shapes_pie_chart.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_directory_files", "examples\core_directory_files.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4397,198 +4405,222 @@ Global {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.Build.0 = Debug|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.ActiveCfg = Debug|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.Build.0 = Debug|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.ActiveCfg = Debug|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.Build.0 = Debug|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.ActiveCfg = Release|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.Build.0 = Release|ARM64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.ActiveCfg = Release|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.Build.0 = Release|x64 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.ActiveCfg = Release|Win32 - {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.Build.0 = Release|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.Build.0 = Debug|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.ActiveCfg = Debug|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.Build.0 = Debug|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.ActiveCfg = Debug|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.Build.0 = Debug|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.ActiveCfg = Release|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.Build.0 = Release|ARM64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.ActiveCfg = Release|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.Build.0 = Release|x64 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.ActiveCfg = Release|Win32 - {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.Build.0 = Release|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.Build.0 = Debug|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.ActiveCfg = Debug|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.Build.0 = Debug|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.ActiveCfg = Debug|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.Build.0 = Debug|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.ActiveCfg = Release|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.Build.0 = Release|ARM64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.ActiveCfg = Release|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.Build.0 = Release|x64 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.ActiveCfg = Release|Win32 - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.Build.0 = Release|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.Build.0 = Debug|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.ActiveCfg = Debug|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.Build.0 = Debug|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.ActiveCfg = Debug|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.Build.0 = Debug|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.ActiveCfg = Release|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.Build.0 = Release|ARM64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.ActiveCfg = Release|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.Build.0 = Release|x64 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.ActiveCfg = Release|Win32 - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.Build.0 = Release|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.Build.0 = Debug|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.ActiveCfg = Debug|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.Build.0 = Debug|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.ActiveCfg = Debug|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.Build.0 = Debug|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.ActiveCfg = Release|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.Build.0 = Release|ARM64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.ActiveCfg = Release|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.Build.0 = Release|x64 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.ActiveCfg = Release|Win32 - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.Build.0 = Release|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.Build.0 = Debug|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.ActiveCfg = Debug|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.Build.0 = Debug|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.ActiveCfg = Debug|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.Build.0 = Debug|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.ActiveCfg = Release|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.Build.0 = Release|ARM64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.ActiveCfg = Release|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.Build.0 = Release|x64 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.ActiveCfg = Release|Win32 - {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.Build.0 = Release|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.Build.0 = Debug|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.ActiveCfg = Debug|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.Build.0 = Debug|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.ActiveCfg = Debug|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.Build.0 = Debug|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.ActiveCfg = Release|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.Build.0 = Release|ARM64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.ActiveCfg = Release|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.Build.0 = Release|x64 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.ActiveCfg = Release|Win32 - {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.Build.0 = Release|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.Build.0 = Debug|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.ActiveCfg = Debug|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.Build.0 = Debug|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.ActiveCfg = Debug|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.Build.0 = Debug|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.ActiveCfg = Release|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.Build.0 = Release|ARM64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.ActiveCfg = Release|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.Build.0 = Release|x64 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.ActiveCfg = Release|Win32 - {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.Build.0 = Debug|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.ActiveCfg = Debug|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.Build.0 = Debug|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.ActiveCfg = Debug|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.Build.0 = Debug|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.ActiveCfg = Release|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.Build.0 = Release|ARM64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.ActiveCfg = Release|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.Build.0 = Release|x64 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.ActiveCfg = Release|Win32 + {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.Build.0 = Release|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.Build.0 = Debug|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.ActiveCfg = Debug|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.Build.0 = Debug|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.ActiveCfg = Debug|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.Build.0 = Debug|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.ActiveCfg = Release|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.Build.0 = Release|ARM64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.ActiveCfg = Release|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4768,15 +4800,10 @@ Global {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021} - {A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} - {5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} - {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} - {0C442799-B09C-4CD1-9538-711B6E85E9BF} = {278D8859-20B1-428F-8448-064F46E1F021} - {DFB40A10-F8B7-412A-BCC3-5EE49294D816} = {278D8859-20B1-428F-8448-064F46E1F021} - {BB58A5FB-1A35-4471-86D0-A5189EC541B3} = {278D8859-20B1-428F-8448-064F46E1F021} - {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {8716DC0F-4FDE-4F57-8E25-5F78DFB80FE1} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index 60da00dd5..e9a70930b 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -60,6 +60,7 @@ Example elements validated: | core_render_texture | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_undo_redo | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_input_actions | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_directory_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bullet_hell | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -85,7 +86,6 @@ Example elements validated: | shapes_dashed_line | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_triangle_strip | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_vector_angle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -195,3 +195,4 @@ Example elements validated: | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From 21404d958ef7d78727c6984d87dddc9b128e538c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20=E2=9D=A4=EF=B8=8F?= Date: Wed, 15 Oct 2025 13:28:38 -0400 Subject: [PATCH 016/102] [examples] Added `core_clipboard_text` (#5231) * added clipboard example * added image check * added note about windows * added indent --- examples/core/core_clipboard_text.c | 208 ++++++++++++++++++++++++++ examples/core/core_clipboard_text.png | Bin 0 -> 15878 bytes 2 files changed, 208 insertions(+) create mode 100644 examples/core/core_clipboard_text.c create mode 100644 examples/core/core_clipboard_text.png diff --git a/examples/core/core_clipboard_text.c b/examples/core/core_clipboard_text.c new file mode 100644 index 000000000..973163cb5 --- /dev/null +++ b/examples/core/core_clipboard_text.c @@ -0,0 +1,208 @@ +/******************************************************************************************* +* +* raylib [core] example - clipboard text +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.6-dev +* +* Example contributed by Robin (@RobinsAviary) 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) 2025-2025 Robin (@RobinsAviary) +* +********************************************************************************************/ + +#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 - clipboard text"); + + const char* clipboardText = NULL; + + // List of text the user can switch through and copy + const char* copyableText[] = {"raylib is fun", "hello, clipboard!", "potato chips"}; + + unsigned int textIndex = 0; + + const char* popupText = NULL; + + // Initialize timers + // The amount of time the pop-up text is on screen, before fading + const float maxTime = 3.0f; + float textTimer = 0.0f; + // The length of time text is offset + const float animMaxTime = 0.1f; + float pasteAnim = 0.0f; + float copyAnim = 0.0f; + int copyAnimMult = 1; + float textAnim = 0.0f; + float textAlpha = 0.0f; + // Offset amount for animations + const int offsetAmount = -4; + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Check if the user has pressed the copy/paste key combinations + bool pastePressed = (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)); + bool copyPressed = (IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)); + + // Update animation timers + if (textTimer > 0) textTimer -= GetFrameTime(); + if (pasteAnim > 0) pasteAnim -= GetFrameTime(); + if (copyAnim > 0) copyAnim -= GetFrameTime(); + if (textAnim > 0) textAnim -= GetFrameTime(); + + // React to the user pressing paste + if (pastePressed) + { + // Most operating systems hide this information until the user presses Ctrl-V on the window. + + // Check to see if the clipboard contains an image + // This function does nothing outside of Windows, as it directly calls the Windows API + Image image = GetClipboardImage(); + + if (IsImageValid(image)) + { + // Unload the image + UnloadImage(image); + // Update visuals + popupText = "clipboard contains image"; + } + else + { + // Get text from the user's clipboard + clipboardText = GetClipboardText(); + + // Update visuals + popupText = "text pasted"; + pasteAnim = animMaxTime; + } + + // Reset animation values + textTimer = maxTime; + textAnim = animMaxTime; + textAlpha = 1; + } + + // React to the user pressing copy + if (copyPressed) + { + // Set the text on the user's clipboard + SetClipboardText(copyableText[textIndex]); + + // Reset values + textTimer = maxTime; + textAnim = animMaxTime; + copyAnim = animMaxTime; + copyAnimMult = 1; + textAlpha = 1; + // Update the text that pops up at the bottom of the screen + popupText = "text copied"; + } + + // Switch to the next item in the list when the user presses up + if (IsKeyPressed(KEY_UP)) + { + // Reset animation + copyAnim = animMaxTime; + copyAnimMult = 1; + + textIndex += 1; + + if (textIndex >= sizeof(copyableText) / sizeof(const char*)) // Length of array + { + // Loop back to the other end + textIndex = 0; + } + } + + // Switch to the previous item in the list when the user presses down + if (IsKeyPressed(KEY_DOWN)) + { + // Reset animation + copyAnim = animMaxTime; + copyAnimMult = -1; + + if (textIndex == 0) + { + // Loop back to the other end + textIndex = (sizeof(copyableText) / sizeof(const char*)) - 1; // Length of array minus one + } + else + { + textIndex -= 1; + } + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw the user's pasted text, if there is any yet + if (clipboardText) + { + // Offset animation + int offset = 0; + if (pasteAnim > 0) offset = offsetAmount; + + // Draw the pasted text + DrawText("pasted clipboard:", 10, 10 + offset, 20, DARKGREEN); + DrawText(clipboardText, 10, 30 + offset, 20, DARKGRAY); + } + + // Offset animation + int textOffset = 0; + if (copyAnim > 0) textOffset = offsetAmount; + + // Draw copyable text and controls + DrawText(copyableText[textIndex], 10, 330 + (textOffset * copyAnimMult), 20, MAROON); + DrawText("up/down to change string, ctrl-c to copy, ctrl-v to paste", 10, 355, 20, DARKGRAY); + + // Alpha / Offset animation + if (textAlpha > 0) + { + // Offset animation + int offset = 0; + if (textAnim > 0) offset = offsetAmount; + // Draw pop up text + DrawText(popupText, 10, 425 + offset, 20, ColorAlpha(DARKGREEN, textAlpha)); + + // Fade-out animation + if (textTimer < 0) + { + textAlpha -= GetFrameTime(); + } + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/core/core_clipboard_text.png b/examples/core/core_clipboard_text.png new file mode 100644 index 0000000000000000000000000000000000000000..caa9b314a694bdb9316f9f8d07161887d53887e6 GIT binary patch literal 15878 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%11B2~ZPZ!6Kin!!IzrMb% zZwoY#Vp^<-gDBx(Ty`-)j<@lmfCN^8v8wez278Lh+TOMU85})W2!oz72RGq^*d=?~ z4s76VyeK*0qKhpqXE{CC z6@%U$Pt`jkQ*>B7ykg;P_w_#(m+o26em!HR5w`fWa7rj)OEFRH!;(3-uSAs)cnlcC9Bj$lDFJC?3i88JN1W}>EGUIhM2)3#l$Sk zwAff-v1UGoU!neQ$WwIK9K4|;_HqBaV5eUv=6Whzw_Th$afg5e@BNEYusPkq2OLVv zCgTgGv+o%fewAZNa?bi9$NOuEX4d<;ir23$UY^i9Z4stJEu6uDk%~7k<}oUkuC?Fz zYUSQ^mRgm0SN5u2xp&!N-QSk9ybMwK4I&=dpFMqF9@&*%ax8m`h%81XJtzqYi())s zap1?-*Vq3axnZ_zSzW=>Qx|_o=&C|P3MIL;B|*aAHl8p5mj<|V;ssq6H*1B(ow<0N zxpT(yW#3tsD#Y z@-NxNY`es>RDarX3%0q z2Tw@qn-5P1XtfgKu2zPV#tKW`9b7Q2s^~p)W2?%><;j87{hWKhM+m(BcX6-D;-zP> zdCH;Xzzd!e8M~yh26^K}fd$bV26cabeYH2-cF^sNyT7Z{oR!5Ub#C6h*c`J^0Fs(Y z@T4Y#Ta1#vIoN#)3MbhK7fnDk_L}*RQ^N~eg~b!?aRsY^6w{Qp122TuTr|NO^lwK% z#R_U(3~=2(>V!ek$Qq4^(TD)o0E45=KbjmzljCS|gpV7HW=c>{jE2H!D8M>)qiJC@ zEsUlG95I?BMsvhyjzFKz87&t^%Z1T$VYFNrEf>H83TVV=={QMn zh*mIyxud1yXz4gwI*yi(qopIbI7A~xOUI#9I&PAkFxkqFN1;b9=*6QQS0+jyx?+}Z zvbG;NcOxR$gA1}g%MRB!~TqolQF}ND}mW*jCX5-{(9z|ne^I! z#?LQB&okmM7d3*6W(B)NZh`83$cSbNH@x^nxLqJb5&(X1wSEGvS+Yd>FzG4;gnuls8+a%lFA*%#WYZb@qXlR5hs z+mbb9$cn+>e_*F#AsFsDHKcB6`T8QR?P3UyMQexc!OISVe`3)O4ifOP!#9kQzQWkt z02XtGn(+~z8C#f*X59e$5gYMBjA^m#go{VaaODW_$~|VVb=Zi*`Ven?rN{}++n9x9 zWzRAkI?^Vx@)diul#JFp`Bx8ZE`0P`{Xu%&N28!a*(UM4@4^mdSjj}L-FESh#Vs#+ zUdB_9m9e7uR>nrOMMWG=vjr_=o#g`#f)1X>i+_w}g@8E-g3TL}m5*Z2Du}F{CU@a! z=iT{^Z%*iJ{3a}2v}9NQg1`Kq#dqz#c(_08p`S*KXDPdn?aq%5YpOGH?G(!=NXuX8 zOZWP$zV))`x&mpPhpw5NKC3@Sz4Z@(h|J1kc zSx|mEVaF2ZtoGXp-t8@EDHs0wXYF;$`stZt>HDVVVaDtV6PC7Qu*xGiKY49q+%79-TFOu3*YG{Rm$a_G+iB1;{yIot zuEJLY>MTyQm0~(<$#Nq0w)HHn0Oy7)1v0i@Q%zVeDzUg-eweXK3c68(5!@p zGFrsAIfFMH*eWb8w7^-iNHM*DxJeB|H*6vP;3%F3K?ynP1eVdX0BXF9hQeqljFyhb zwGI_>M8`bFhj|9+3=bRmnhrkV%W6OD@H2Zy+w+V>Q*5;tXe%4%wTx5P_bfp+(112! z3g5=nxB%}PYnRY`4~s@*wM)i-#re{%wAkviag4tX=3LNdIpuzW!fCMyl{i<=02v zaZ0Y(;`q*oQL*;PxhFm6VtS?tVe4Ty8-jZnm*3(FOHgks%~)Yc-$oSmGxdy(Yz+{qw%ivlr14x_wMmPnl^m+np=<_r_kZ*4etykeShO{$s9;0 zrxstJ65M47?#AKXfK|fXD7c$F#iSQ^PYT-Cyo)Cq5@_DnWN Date: Wed, 15 Oct 2025 23:00:37 +0530 Subject: [PATCH 017/102] feat(shapes): Add shapes_mouse_trail.c example and screenshot (#5246) Co-authored-by: Balamurugan R --- examples/shapes/shapes_mouse_trail.c | 106 +++++++++++++++++++++++++ examples/shapes/shapes_mouse_trail.png | Bin 0 -> 5525 bytes 2 files changed, 106 insertions(+) create mode 100644 examples/shapes/shapes_mouse_trail.c create mode 100644 examples/shapes/shapes_mouse_trail.png diff --git a/examples/shapes/shapes_mouse_trail.c b/examples/shapes/shapes_mouse_trail.c new file mode 100644 index 000000000..b1cb706f2 --- /dev/null +++ b/examples/shapes/shapes_mouse_trail.c @@ -0,0 +1,106 @@ +#include "raylib.h" +#include "raymath.h" + +/******************************************************************************************* +* +* raylib [shapes] example - Draw a mouse trail (position history) +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.6 +* +* Example contributed by [Balamurugan R] (@[Bala050814]]) and reviewed by [Ray] (@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 [Balamurugan R] (@[Bala050814]) +* +********************************************************************************************/ + +// Define the maximum number of positions to store in the trail +#define MAX_TRAIL_LENGTH 30 + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - Draw a mouse trail"); + + // Array to store the history of mouse positions (our fixed-size queue) + Vector2 trailPositions[MAX_TRAIL_LENGTH] = { 0 }; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + Vector2 mousePosition = GetMousePosition(); + + // 1. Shift all existing positions backward by one slot in the array + // The last element (the oldest position) is dropped. + for (int i = MAX_TRAIL_LENGTH - 1; i > 0; i--) + { + trailPositions[i] = trailPositions[i - 1]; + } + + // 2. Store the new, current mouse position at the start of the array (Index 0) + trailPositions[0] = mousePosition; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + // Use BLACK for a darker background to make the colored trail pop + ClearBackground(BLACK); + + // 3. Draw the trail by looping through the history array + for (int i = 0; i < MAX_TRAIL_LENGTH; i++) + { + // Ensure we skip drawing if the array hasn't been fully filled on startup + if (trailPositions[i].x != 0.0f || trailPositions[i].y != 0.0f) + { + // Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old) + float ratio = (float)(MAX_TRAIL_LENGTH - i) / MAX_TRAIL_LENGTH; + + // Fade effect: oldest positions are more transparent + // Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio + Color trailColor = Fade(SKYBLUE, ratio * 0.5f + 0.5f); + + // Size effect: oldest positions are smaller + float trailRadius = 15.0f * ratio; + + DrawCircleV(trailPositions[i], trailRadius, trailColor); + } + } + + // Draw a distinct white circle for the current mouse position (Index 0) + DrawCircleV(mousePosition, 15.0f, WHITE); + + DrawText("Move the mouse to see the trail effect!", + 10, screenHeight - 30, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // No resources loaded, nothing to unload. + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_mouse_trail.png b/examples/shapes/shapes_mouse_trail.png new file mode 100644 index 0000000000000000000000000000000000000000..aa64efcdf420f0fa303aec119ce48dd5e9f20759 GIT binary patch literal 5525 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

jHT7OG)qA)1=P4Tz!HW_SPD~65`rs<% zhezaSM|v~_hzkJ+eZRR@qRai}o;u8s!w614GBdubdw)I`Zyvk<|GLi+eE+LUE`Plr ze7({+^6T~aC+@rNd&cxXjv*s?IcSvTW@p#7`7T@Uvfs$}n`0rU?lU zc>Dj==RW;)y`F#h%h%1zzJB^W`&sJGTHj}}`7eIv&boH`eg3TJxxc>O{PO?vpV}=e z>+Y(3K9@atf8FeDKY#vy_3JOwhRQeK5v1xeEwx#7kER^|TsrOj^Vd4}&tH$c{ddjl zKievQ*6llY>s@-~zdhF@_sw6wxyC+zd*W%jSF_UFdk{=4S=PpFdE=iASo{{Ff2 z8d&c2o^_w9a<9j3-K&59{B_@7v!=g){@N_|dHG!S1J5=FgT|#y+>UmN)@pf84mP&? zner)kW9g**`%C}YiBJ8%^ON@J@3Wt+-Tmk9^YCf!&Ckw0@%h%X^fc%>D2> zUfue=+tyou*|Y5@!-eUf!j0j@qK`hVlTZ5Z-DNlXc8Pue^ViENLu0RJ&j#7NYR^5W z2e$o=oHu{{>Rs!uo2`HQZ_lTypS#ZP`Fy)1c71N#K8Qr=J(t^mYWBa~wYu{D_0qcg zpVivt@gMjGarKvN!55ch{@oK77Hgj!t^dE+bnWc-+t*rO+!A+fOWp0#*`;&uFU#E< zT6?$Cb^pITpKotjJAHrN|Ufew2 zx#Ra=&@f@dfve{`e{9`;^kVz|S0B|G7!v% Date: Wed, 15 Oct 2025 19:33:53 +0200 Subject: [PATCH 018/102] Added text alignment example (#5254) Co-authored-by: Ray --- examples/Makefile | 3 +- examples/Makefile.Web | 3 +- examples/README.md | 3 +- examples/examples_list.txt | 1 + examples/text/text_words_alignment.c | 130 +++++++++++++++++++++++++ examples/text/text_words_alignment.png | Bin 0 -> 15745 bytes 6 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 examples/text/text_words_alignment.c create mode 100644 examples/text/text_words_alignment.png diff --git a/examples/Makefile b/examples/Makefile index 8b5faf634..69d100fdb 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -612,7 +612,8 @@ TEXT = \ text/text_sprite_fonts \ text/text_unicode_emojis \ text/text_unicode_ranges \ - text/text_writing_anim + text/text_writing_anim \ + text/text_words_alignment MODELS = \ models/models_animation_gpu_skinning \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 510725b6e..933ea3499 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -612,7 +612,8 @@ TEXT = \ text/text_sprite_fonts \ text/text_unicode_emojis \ text/text_unicode_ranges \ - text/text_writing_anim + text/text_writing_anim \ + text/text_words_alignment MODELS = \ models/models_animation_gpu_skinning \ diff --git a/examples/README.md b/examples/README.md index 3468ff34a..9757cea60 100644 --- a/examples/README.md +++ b/examples/README.md @@ -133,7 +133,7 @@ Examples using raylib textures functionality, including image/textures loading/g | [textures_image_rotate](textures/textures_image_rotate.c) | textures_image_rotate | ⭐⭐☆☆ | 1.0 | 1.0 | [Ramon Santamaria](https://github.com/raysan5) | | [textures_textured_curve](textures/textures_textured_curve.c) | textures_textured_curve | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jeffery Myers](https://github.com/JeffM2501) | -### category: text [14] +### category: text [15] Examples using raylib text functionality, including sprite fonts loading/generation and text drawing, provided by raylib [text](../src/rtext.c) module. @@ -153,6 +153,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat | [text_3d_drawing](text/text_3d_drawing.c) | text_3d_drawing | ⭐⭐⭐⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [text_inline_styling](text/text_inline_styling.c) | text_inline_styling | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | +| [text_words_alignment](text/text_words_alignment.c) | text_words_alignment | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: models [25] diff --git a/examples/examples_list.txt b/examples/examples_list.txt index ed904d6f1..9770975fb 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -114,6 +114,7 @@ text;text_unicode_ranges;★★★★;5.5;5.6;2025;2025;"Vadim Gunko";@GuvaCode text;text_3d_drawing;★★★★;3.5;4.0;2021;2025;"Vlad Adrian";@demizdor text;text_codepoints_loading;★★★☆;4.2;4.2;2022;2025;"Ramon Santamaria";@raysan5 text;text_inline_styling;★★★☆;5.6-dev;5.6-dev;2025;2025;"Wagner Barongello";@SultansOfCode +text;text_words_alignment;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates models;models_animation_playing;★★☆☆;2.5;3.5;2019;2025;"Culacant";@culacant models;models_billboard_rendering;★★★☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5 models;models_box_collisions;★☆☆☆;1.3;3.5;2015;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/text/text_words_alignment.c b/examples/text/text_words_alignment.c new file mode 100644 index 000000000..0f012ab75 --- /dev/null +++ b/examples/text/text_words_alignment.c @@ -0,0 +1,130 @@ +/******************************************************************************************* +* +* raylib [text] example - text alignment +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.0, last time updated with raylib 5.5 +* +* Example contributed by JP Mortiboys (@themushroompirates) 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) 2025 JP Mortiboys (@themushroompirates) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" // Required for: Lerp() + +typedef enum TextAlignment { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_CENTRE = 1, + TEXT_ALIGN_MIDDLE = 1, + TEXT_ALIGN_RIGHT = 2, + TEXT_ALIGN_BOTTOM = 2 +} TextAlignment; + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [text] example - text alignment"); + + // Define the rectangle we will draw the text in + Rectangle textContainerRect = (Rectangle){ screenWidth/2-screenWidth/4, screenHeight/2-screenHeight/3, screenWidth/2, screenHeight*2/3 }; + + // Some text to display the current alignment + const char *textAlignNameH[] = { "Left", "Centre", "Right" }; + const char *textAlignNameV[] = { "Top", "Middle", "Bottom" }; + + // Define the text we're going to draw in the rectangle + int wordIndex = 0; + int wordCount = 0; + char **words = TextSplit("raylib is a simple and easy-to-use library to enjoy videogames programming", ' ', &wordCount); + + // Initialize the font size we're going to use + int fontSize = 40; + + // And of course the font... + Font font = GetFontDefault(); + + // Intialize the alignment variables + TextAlignment hAlign = TEXT_ALIGN_CENTRE; + TextAlignment vAlign = TEXT_ALIGN_MIDDLE; + + 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 + //---------------------------------------------------------------------------------- + + if (IsKeyPressed(KEY_LEFT)) { + hAlign = hAlign - 1; + if (hAlign < 0) hAlign = 0; + } + if (IsKeyPressed(KEY_RIGHT)) { + hAlign = hAlign + 1; + if (hAlign > 2) hAlign = 2; + } + if (IsKeyPressed(KEY_UP)) { + vAlign = vAlign - 1; + if (vAlign < 0) vAlign = 0; + } + if (IsKeyPressed(KEY_DOWN)) { + vAlign = vAlign + 1; + if (vAlign > 2) vAlign = 2; + } + + // One word per second + wordIndex = (int)GetTime() % wordCount; + + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(DARKBLUE); + + DrawText("Use Arrow Keys to change the text alignment", 20, 20, 20, LIGHTGRAY); + DrawText(TextFormat("Alignment: Horizontal = %s, Vertical = %s", textAlignNameH[hAlign], textAlignNameV[vAlign]), 20, 40, 20, LIGHTGRAY); + + DrawRectangleRec(textContainerRect, BLUE); + + // Get the size of the text to draw + Vector2 textSize = MeasureTextEx(font, words[wordIndex], fontSize, fontSize*.1f); + + // Calculate the top-left text position based on the rectangle and alignment + Vector2 textPos = (Vector2) { + textContainerRect.x + Lerp(0.0f, textContainerRect.width - textSize.x, ((float)hAlign) * 0.5f), + textContainerRect.y + Lerp(0.0f, textContainerRect.height - textSize.y, ((float)vAlign) * 0.5f) + }; + + // Draw the text + DrawTextEx(font, words[wordIndex], textPos, fontSize, fontSize*.1f, RAYWHITE); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/text/text_words_alignment.png b/examples/text/text_words_alignment.png new file mode 100644 index 0000000000000000000000000000000000000000..ae0892381437200ccf3fd6e74005250d658e2282 GIT binary patch literal 15745 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%11B0!Hr;B4qMO<fU4wiJ`Veq7GDpv&TBt+2Q=7pEKYAa2OPW<5kqcEUvy+)nrdaYE>*6WCHrhI}X- zaLS$SH|1nQ@0J%;P1iG$u3pquNqDDt&Ccncv|eV#ieu_4AKKrzq^$RyU$p#^^?kl? zpVBrQx$Ur%dHP;uTigC;&o5rP2hI^5yp0znCtTcOk3D5CR&>}dkRZvMeMLZ_Or_N1 z4kC+aa5qjgnrt)64?9LSZ|Ki!A-R-x&P0E&2tbOuq^1*5II?rxzdBmH>xAstP z)H@aPKb~jbA88ZUs}IzcUoc(1S@-Y7TedqcJ$-TJLWXt$I4A9BKk$O*M23_+Z{tM) z2`t2dXbzrTwhBx7{s>6@R5n%Vl>O*rK0WH)v8QoGe=D0#1fS$+6<$}M_#{8;IRDaz zekbN1Ii|ezuj}fPe8(r5B}dw{SH5hBdd04Fk4|-;#s62_xz8Kmt$|Uvx#d9j-EAVRPoV zP}P4ZL+7#@i`(N|lhi^${><+oDH$AY!?azh7(=UCHU-QvDt43hXX%|!x%b|2&Ds%cZU5lbVviMZO55)p5|!Vg zC7XV`choz_WdGPWF-L(xU6$ZKIWk*D9 z%N5>le;A7Yb8`95UQ}wQxV3IUsjcm;X;9l4V-yXnn2lzcA<9-X)(bJF=6@n<7ETgt zd*vat*G+AuXuo>fiOTO^y!fxgefG<<;l29BfBnoTr+g?7+ zi>c=5@V)MAT659+`on4RZC-yZV=kS~s7?i&`lAJ$8ME+ZMxI@g0!i*H?6+ryIlWt0 z!ooHEr$I4$mdc!Knxc2_w;W=8CKt7wKWgXWBMj$LCQ9cq&;57Ow|&X3-z-!89F?xl zIViR7Nt^t}kEKa7&c2y6YyXMR{y6yyR)2f8-Gqi)!xaIExr~y&#?Taq*-|RuW^`*? zVEVs3xMIG3G-%@0a4tpV{`63IV7+J#Is94S=wln*R`{gSj za}H#1Ops<;yqu$V*<5hgLx}}(96je6dX_DN@-b>D#$BxkHr!@5npFn%3b>R&A=vUE zW}L%kMh3w$1#b&9VGFa-EH<1@Xp4t9;nk=U8hVyd77CD>#Lbz(pJT=DKDP7Fo%HU!nN8@_a6`=yZv_K4{n?PK$6yLlIrSrn*F3AvKdhtCd zAdB~x97ok`|5tK6S@%ynzTB(0r0xHUd6O?LN(7JEny_RDgU5z7v!Q&9p+Dk6f#C4d zJ4Q)gSU@@~7g+FZ9+TJE#oy#69h^2n@1P_k z(G(-xh{__IXh5NYcOgT=M8%A=|1WlcJ$*os>D9W$j>e#{b4cS@@c!U}693~FEux8F^v$XeJru(AMEI>Cg6 z;7}TP`wla7d Date: Wed, 15 Oct 2025 19:34:39 +0200 Subject: [PATCH 019/102] Added simple starfield example (#5255) --- examples/Makefile | 1 + examples/Makefile.Web | 1 + examples/README.md | 3 +- examples/shapes/shapes_starfield.c | 143 +++++++++++++++++++++++++++ examples/shapes/shapes_starfield.png | Bin 0 -> 20913 bytes 5 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 examples/shapes/shapes_starfield.c create mode 100644 examples/shapes/shapes_starfield.png diff --git a/examples/Makefile b/examples/Makefile index 69d100fdb..523339d06 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -566,6 +566,7 @@ SHAPES = \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ + shapes/shapes_starfield \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 933ea3499..c5e9138f5 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -566,6 +566,7 @@ SHAPES = \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_splines_drawing \ + shapes/shapes_starfield \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle diff --git a/examples/README.md b/examples/README.md index 9757cea60..16e44aa2b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -67,7 +67,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | -### category: shapes [26] +### category: shapes [27] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -93,6 +93,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) | | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐⭐⭐⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) | | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | shapes_splines_drawing | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | +| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐⭐⭐☆ | 5.5 | 5.5 | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_digital_clock](shapes/shapes_digital_clock.c) | shapes_digital_clock | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) | | [shapes_double_pendulum](shapes/shapes_double_pendulum.c) | shapes_double_pendulum | ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) | | [shapes_dashed_line](shapes/shapes_dashed_line.c) | shapes_dashed_line | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) | diff --git a/examples/shapes/shapes_starfield.c b/examples/shapes/shapes_starfield.c new file mode 100644 index 000000000..457912dec --- /dev/null +++ b/examples/shapes/shapes_starfield.c @@ -0,0 +1,143 @@ +/******************************************************************************************* +* +* raylib [shapes] example - simple starfield +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5 +* +* Example contributed by JP Mortiboys (@themushroompirates) 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) 2025 JP Mortiboys (@themushroompirates) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" // Required for: Lerp() + +#define STAR_COUNT 420 + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield"); + + Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.69f); + + // Speed at which we fly forward + float speed = 10.0f/9.0f; + + // We're either drawing lines or circles + bool drawLines = true; + + Vector3 stars[STAR_COUNT] = { 0 }; + Vector2 starsScreenPos[STAR_COUNT] = { 0 }; + + // Setup the stars with a random position + for (int i = 0; i < STAR_COUNT; i++) { + stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); + stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + stars[i].z = 1.0f; + } + + 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 + //---------------------------------------------------------------------------------- + + // Change speed based on number keys + for (int i = 0; i <= 9; i++) { + if (IsKeyPressed(KEY_ZERO + i)) { + speed = 2.0f * (float)i / 9.0f; + } + } + + // Toggle lines / points with space bar + if (IsKeyPressed(KEY_SPACE)) { + drawLines = !drawLines; + } + + float dt = GetFrameTime(); + for (int i = 0; i < STAR_COUNT; i++) { + // Update star's timer + stars[i].z -= dt * speed; + // Calculate the screen position + starsScreenPos[i] = (Vector2) { + screenWidth*.5f + stars[i].x / stars[i].z, + screenHeight*.5f + stars[i].y / stars[i].z, + }; + // If the star is too old, or offscreen, it dies and we make a new random one + if (stars[i].z < 0.0f + || starsScreenPos[i].x < 0 || starsScreenPos[i].y < 0.0f + || starsScreenPos[i].x > screenWidth || starsScreenPos[i].y > screenHeight) { + stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); + stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + stars[i].z = 1.0f; + } + } + + + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(bgColor); + + for (int i = 0; i < STAR_COUNT; i++) { + if (drawLines) { + // Get the time a little while ago for this star, but clamp it + float t = Clamp(stars[i].z + 1.0f/32.0f, 0.0f, 1.0f); + // If it's different enough from the current time, we proceed + if (t - stars[i].z > 1e-3) { + // Calculate the screen position of the old point + Vector2 startPos = (Vector2) { + screenWidth*.5f + stars[i].x / t, + screenHeight*.5f + stars[i].y / t, + }; + // Draw a line connecting the old point to the current point + DrawLineV(startPos, starsScreenPos[i], RAYWHITE); + } + } + else { + // Make the radius grow as the star ages + float radius = Lerp(stars[i].z, 1.0f, 5.0f); + // Draw the circle + DrawCircleV(starsScreenPos[i], radius, RAYWHITE); + } + } + + DrawFPS(10, 10); + + DrawText(TextFormat("Current Speed: %.0f [Number keys to change]", 9.0f * speed / 2.0f), 10, 30, 20, RAYWHITE); + DrawText(TextFormat("Drawing %s [Space to change]", drawLines ? "Lines" : "Circles"), 10, 50, 20, RAYWHITE); + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_starfield.png b/examples/shapes/shapes_starfield.png new file mode 100644 index 0000000000000000000000000000000000000000..6903f222b5e0e25b22be5717b79da5b66f6503d5 GIT binary patch literal 20913 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 KelF{r5}E)p$5%7} literal 0 HcmV?d00001 From fd28db53ad24601ab4bf78faa462a14a6f8c337b Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Oct 2025 19:35:59 +0200 Subject: [PATCH 020/102] Update parse_api.yml --- .github/workflows/parse_api.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/parse_api.yml b/.github/workflows/parse_api.yml index ce7cb9f9a..e095e4a55 100644 --- a/.github/workflows/parse_api.yml +++ b/.github/workflows/parse_api.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 - name: Update parse files - working-directory: tools/parser + working-directory: tools/rlparser run: | make raylib_api mv raylib_api.* output @@ -22,7 +22,7 @@ jobs: - name: Diff parse files id: diff run: | - git add -N tools/parser + git add -N tools/rlparser git diff --name-only --exit-code continue-on-error: true From b020bed2b3388d7a6d2d014bee28ef3a1ff99de7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:36:24 +0000 Subject: [PATCH 021/102] rlparser: update raylib_api.* by CI --- tools/rlparser/output/raylib_api.json | 15 + tools/rlparser/output/raylib_api.lua | 9 + tools/rlparser/output/raylib_api.txt | 884 +++++++++++++------------- tools/rlparser/output/raylib_api.xml | 6 +- tools/rlparser/rlparser | Bin 0 -> 43144 bytes 5 files changed, 474 insertions(+), 440 deletions(-) create mode 100755 tools/rlparser/rlparser diff --git a/tools/rlparser/output/raylib_api.json b/tools/rlparser/output/raylib_api.json index 9714d5d05..c0bc88681 100644 --- a/tools/rlparser/output/raylib_api.json +++ b/tools/rlparser/output/raylib_api.json @@ -4851,6 +4851,21 @@ } ] }, + { + "name": "ComputeSHA256", + "description": "Compute SHA256 hash code, returns static int[8] (32 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/tools/rlparser/output/raylib_api.lua b/tools/rlparser/output/raylib_api.lua index 75fd06373..5cb3c1d55 100644 --- a/tools/rlparser/output/raylib_api.lua +++ b/tools/rlparser/output/raylib_api.lua @@ -4296,6 +4296,15 @@ return { {type = "int", name = "dataSize"} } }, + { + name = "ComputeSHA256", + description = "Compute SHA256 hash code, returns static int[8] (32 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/tools/rlparser/output/raylib_api.txt b/tools/rlparser/output/raylib_api.txt index 849a97a56..9be8e517c 100644 --- a/tools/rlparser/output/raylib_api.txt +++ b/tools/rlparser/output/raylib_api.txt @@ -993,7 +993,7 @@ Callback 006: AudioCallback() (2 input parameters) Param[1]: bufferData (type: void *) Param[2]: frames (type: unsigned int) -Functions found: 596 +Functions found: 597 Function 001: InitWindow() (3 input parameters) Name: InitWindow @@ -1851,148 +1851,154 @@ Function 158: ComputeSHA1() (2 input parameters) Description: Compute SHA1 hash code, returns static int[5] (20 bytes) Param[1]: data (type: unsigned char *) Param[2]: dataSize (type: int) -Function 159: LoadAutomationEventList() (1 input parameters) +Function 159: ComputeSHA256() (2 input parameters) + Name: ComputeSHA256 + Return type: unsigned int * + Description: Compute SHA256 hash code, returns static int[8] (32 bytes) + Param[1]: data (type: unsigned char *) + Param[2]: dataSize (type: int) +Function 160: 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 160: UnloadAutomationEventList() (1 input parameters) +Function 161: UnloadAutomationEventList() (1 input parameters) Name: UnloadAutomationEventList Return type: void Description: Unload automation events list from file Param[1]: list (type: AutomationEventList) -Function 161: ExportAutomationEventList() (2 input parameters) +Function 162: 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 162: SetAutomationEventList() (1 input parameters) +Function 163: SetAutomationEventList() (1 input parameters) Name: SetAutomationEventList Return type: void Description: Set automation event list to record to Param[1]: list (type: AutomationEventList *) -Function 163: SetAutomationEventBaseFrame() (1 input parameters) +Function 164: 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 164: StartAutomationEventRecording() (0 input parameters) +Function 165: StartAutomationEventRecording() (0 input parameters) Name: StartAutomationEventRecording Return type: void Description: Start recording automation events (AutomationEventList must be set) No input parameters -Function 165: StopAutomationEventRecording() (0 input parameters) +Function 166: StopAutomationEventRecording() (0 input parameters) Name: StopAutomationEventRecording Return type: void Description: Stop recording automation events No input parameters -Function 166: PlayAutomationEvent() (1 input parameters) +Function 167: PlayAutomationEvent() (1 input parameters) Name: PlayAutomationEvent Return type: void Description: Play a recorded automation event Param[1]: event (type: AutomationEvent) -Function 167: IsKeyPressed() (1 input parameters) +Function 168: IsKeyPressed() (1 input parameters) Name: IsKeyPressed Return type: bool Description: Check if a key has been pressed once Param[1]: key (type: int) -Function 168: IsKeyPressedRepeat() (1 input parameters) +Function 169: IsKeyPressedRepeat() (1 input parameters) Name: IsKeyPressedRepeat Return type: bool Description: Check if a key has been pressed again Param[1]: key (type: int) -Function 169: IsKeyDown() (1 input parameters) +Function 170: IsKeyDown() (1 input parameters) Name: IsKeyDown Return type: bool Description: Check if a key is being pressed Param[1]: key (type: int) -Function 170: IsKeyReleased() (1 input parameters) +Function 171: IsKeyReleased() (1 input parameters) Name: IsKeyReleased Return type: bool Description: Check if a key has been released once Param[1]: key (type: int) -Function 171: IsKeyUp() (1 input parameters) +Function 172: IsKeyUp() (1 input parameters) Name: IsKeyUp Return type: bool Description: Check if a key is NOT being pressed Param[1]: key (type: int) -Function 172: GetKeyPressed() (0 input parameters) +Function 173: 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 173: GetCharPressed() (0 input parameters) +Function 174: 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 174: GetKeyName() (1 input parameters) +Function 175: GetKeyName() (1 input parameters) Name: GetKeyName Return type: const char * Description: Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard) Param[1]: key (type: int) -Function 175: SetExitKey() (1 input parameters) +Function 176: 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 176: IsGamepadAvailable() (1 input parameters) +Function 177: IsGamepadAvailable() (1 input parameters) Name: IsGamepadAvailable Return type: bool Description: Check if a gamepad is available Param[1]: gamepad (type: int) -Function 177: GetGamepadName() (1 input parameters) +Function 178: GetGamepadName() (1 input parameters) Name: GetGamepadName Return type: const char * Description: Get gamepad internal name id Param[1]: gamepad (type: int) -Function 178: IsGamepadButtonPressed() (2 input parameters) +Function 179: 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 179: IsGamepadButtonDown() (2 input parameters) +Function 180: 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 180: IsGamepadButtonReleased() (2 input parameters) +Function 181: 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 181: IsGamepadButtonUp() (2 input parameters) +Function 182: 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 182: GetGamepadButtonPressed() (0 input parameters) +Function 183: GetGamepadButtonPressed() (0 input parameters) Name: GetGamepadButtonPressed Return type: int Description: Get the last gamepad button pressed No input parameters -Function 183: GetGamepadAxisCount() (1 input parameters) +Function 184: GetGamepadAxisCount() (1 input parameters) Name: GetGamepadAxisCount Return type: int Description: Get axis count for a gamepad Param[1]: gamepad (type: int) -Function 184: GetGamepadAxisMovement() (2 input parameters) +Function 185: GetGamepadAxisMovement() (2 input parameters) Name: GetGamepadAxisMovement Return type: float Description: Get movement value for a gamepad axis Param[1]: gamepad (type: int) Param[2]: axis (type: int) -Function 185: SetGamepadMappings() (1 input parameters) +Function 186: SetGamepadMappings() (1 input parameters) Name: SetGamepadMappings Return type: int Description: Set internal gamepad mappings (SDL_GameControllerDB) Param[1]: mappings (type: const char *) -Function 186: SetGamepadVibration() (4 input parameters) +Function 187: SetGamepadVibration() (4 input parameters) Name: SetGamepadVibration Return type: void Description: Set gamepad vibration for both motors (duration in seconds) @@ -2000,151 +2006,151 @@ Function 186: SetGamepadVibration() (4 input parameters) Param[2]: leftMotor (type: float) Param[3]: rightMotor (type: float) Param[4]: duration (type: float) -Function 187: IsMouseButtonPressed() (1 input parameters) +Function 188: 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 188: IsMouseButtonDown() (1 input parameters) +Function 189: IsMouseButtonDown() (1 input parameters) Name: IsMouseButtonDown Return type: bool Description: Check if a mouse button is being pressed Param[1]: button (type: int) -Function 189: IsMouseButtonReleased() (1 input parameters) +Function 190: 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 190: IsMouseButtonUp() (1 input parameters) +Function 191: 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 191: GetMouseX() (0 input parameters) +Function 192: GetMouseX() (0 input parameters) Name: GetMouseX Return type: int Description: Get mouse position X No input parameters -Function 192: GetMouseY() (0 input parameters) +Function 193: GetMouseY() (0 input parameters) Name: GetMouseY Return type: int Description: Get mouse position Y No input parameters -Function 193: GetMousePosition() (0 input parameters) +Function 194: GetMousePosition() (0 input parameters) Name: GetMousePosition Return type: Vector2 Description: Get mouse position XY No input parameters -Function 194: GetMouseDelta() (0 input parameters) +Function 195: GetMouseDelta() (0 input parameters) Name: GetMouseDelta Return type: Vector2 Description: Get mouse delta between frames No input parameters -Function 195: SetMousePosition() (2 input parameters) +Function 196: 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 196: SetMouseOffset() (2 input parameters) +Function 197: SetMouseOffset() (2 input parameters) Name: SetMouseOffset Return type: void Description: Set mouse offset Param[1]: offsetX (type: int) Param[2]: offsetY (type: int) -Function 197: SetMouseScale() (2 input parameters) +Function 198: SetMouseScale() (2 input parameters) Name: SetMouseScale Return type: void Description: Set mouse scaling Param[1]: scaleX (type: float) Param[2]: scaleY (type: float) -Function 198: GetMouseWheelMove() (0 input parameters) +Function 199: 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 199: GetMouseWheelMoveV() (0 input parameters) +Function 200: GetMouseWheelMoveV() (0 input parameters) Name: GetMouseWheelMoveV Return type: Vector2 Description: Get mouse wheel movement for both X and Y No input parameters -Function 200: SetMouseCursor() (1 input parameters) +Function 201: SetMouseCursor() (1 input parameters) Name: SetMouseCursor Return type: void Description: Set mouse cursor Param[1]: cursor (type: int) -Function 201: GetTouchX() (0 input parameters) +Function 202: 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 202: GetTouchY() (0 input parameters) +Function 203: 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 203: GetTouchPosition() (1 input parameters) +Function 204: 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 204: GetTouchPointId() (1 input parameters) +Function 205: GetTouchPointId() (1 input parameters) Name: GetTouchPointId Return type: int Description: Get touch point identifier for given index Param[1]: index (type: int) -Function 205: GetTouchPointCount() (0 input parameters) +Function 206: GetTouchPointCount() (0 input parameters) Name: GetTouchPointCount Return type: int Description: Get number of touch points No input parameters -Function 206: SetGesturesEnabled() (1 input parameters) +Function 207: SetGesturesEnabled() (1 input parameters) Name: SetGesturesEnabled Return type: void Description: Enable a set of gestures using flags Param[1]: flags (type: unsigned int) -Function 207: IsGestureDetected() (1 input parameters) +Function 208: IsGestureDetected() (1 input parameters) Name: IsGestureDetected Return type: bool Description: Check if a gesture have been detected Param[1]: gesture (type: unsigned int) -Function 208: GetGestureDetected() (0 input parameters) +Function 209: GetGestureDetected() (0 input parameters) Name: GetGestureDetected Return type: int Description: Get latest detected gesture No input parameters -Function 209: GetGestureHoldDuration() (0 input parameters) +Function 210: GetGestureHoldDuration() (0 input parameters) Name: GetGestureHoldDuration Return type: float Description: Get gesture hold time in seconds No input parameters -Function 210: GetGestureDragVector() (0 input parameters) +Function 211: GetGestureDragVector() (0 input parameters) Name: GetGestureDragVector Return type: Vector2 Description: Get gesture drag vector No input parameters -Function 211: GetGestureDragAngle() (0 input parameters) +Function 212: GetGestureDragAngle() (0 input parameters) Name: GetGestureDragAngle Return type: float Description: Get gesture drag angle No input parameters -Function 212: GetGesturePinchVector() (0 input parameters) +Function 213: GetGesturePinchVector() (0 input parameters) Name: GetGesturePinchVector Return type: Vector2 Description: Get gesture pinch delta No input parameters -Function 213: GetGesturePinchAngle() (0 input parameters) +Function 214: GetGesturePinchAngle() (0 input parameters) Name: GetGesturePinchAngle Return type: float Description: Get gesture pinch angle No input parameters -Function 214: UpdateCamera() (2 input parameters) +Function 215: 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 215: UpdateCameraPro() (4 input parameters) +Function 216: UpdateCameraPro() (4 input parameters) Name: UpdateCameraPro Return type: void Description: Update camera movement/rotation @@ -2152,36 +2158,36 @@ Function 215: UpdateCameraPro() (4 input parameters) Param[2]: movement (type: Vector3) Param[3]: rotation (type: Vector3) Param[4]: zoom (type: float) -Function 216: SetShapesTexture() (2 input parameters) +Function 217: 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 217: GetShapesTexture() (0 input parameters) +Function 218: GetShapesTexture() (0 input parameters) Name: GetShapesTexture Return type: Texture2D Description: Get texture that is used for shapes drawing No input parameters -Function 218: GetShapesTextureRectangle() (0 input parameters) +Function 219: GetShapesTextureRectangle() (0 input parameters) Name: GetShapesTextureRectangle Return type: Rectangle Description: Get texture source rectangle that is used for shapes drawing No input parameters -Function 219: DrawPixel() (3 input parameters) +Function 220: 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 220: DrawPixelV() (2 input parameters) +Function 221: 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 221: DrawLine() (5 input parameters) +Function 222: DrawLine() (5 input parameters) Name: DrawLine Return type: void Description: Draw a line @@ -2190,14 +2196,14 @@ Function 221: DrawLine() (5 input parameters) Param[3]: endPosX (type: int) Param[4]: endPosY (type: int) Param[5]: color (type: Color) -Function 222: DrawLineV() (3 input parameters) +Function 223: 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 223: DrawLineEx() (4 input parameters) +Function 224: DrawLineEx() (4 input parameters) Name: DrawLineEx Return type: void Description: Draw a line (using triangles/quads) @@ -2205,14 +2211,14 @@ Function 223: DrawLineEx() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 224: DrawLineStrip() (3 input parameters) +Function 225: 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 225: DrawLineBezier() (4 input parameters) +Function 226: DrawLineBezier() (4 input parameters) Name: DrawLineBezier Return type: void Description: Draw line segment cubic-bezier in-out interpolation @@ -2220,7 +2226,7 @@ Function 225: DrawLineBezier() (4 input parameters) Param[2]: endPos (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 226: DrawLineDashed() (5 input parameters) +Function 227: DrawLineDashed() (5 input parameters) Name: DrawLineDashed Return type: void Description: Draw a dashed line @@ -2229,7 +2235,7 @@ Function 226: DrawLineDashed() (5 input parameters) Param[3]: dashSize (type: int) Param[4]: spaceSize (type: int) Param[5]: color (type: Color) -Function 227: DrawCircle() (4 input parameters) +Function 228: DrawCircle() (4 input parameters) Name: DrawCircle Return type: void Description: Draw a color-filled circle @@ -2237,7 +2243,7 @@ Function 227: DrawCircle() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 228: DrawCircleSector() (6 input parameters) +Function 229: DrawCircleSector() (6 input parameters) Name: DrawCircleSector Return type: void Description: Draw a piece of a circle @@ -2247,7 +2253,7 @@ Function 228: DrawCircleSector() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 229: DrawCircleSectorLines() (6 input parameters) +Function 230: DrawCircleSectorLines() (6 input parameters) Name: DrawCircleSectorLines Return type: void Description: Draw circle sector outline @@ -2257,7 +2263,7 @@ Function 229: DrawCircleSectorLines() (6 input parameters) Param[4]: endAngle (type: float) Param[5]: segments (type: int) Param[6]: color (type: Color) -Function 230: DrawCircleGradient() (5 input parameters) +Function 231: DrawCircleGradient() (5 input parameters) Name: DrawCircleGradient Return type: void Description: Draw a gradient-filled circle @@ -2266,14 +2272,14 @@ Function 230: DrawCircleGradient() (5 input parameters) Param[3]: radius (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 231: DrawCircleV() (3 input parameters) +Function 232: 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 232: DrawCircleLines() (4 input parameters) +Function 233: DrawCircleLines() (4 input parameters) Name: DrawCircleLines Return type: void Description: Draw circle outline @@ -2281,14 +2287,14 @@ Function 232: DrawCircleLines() (4 input parameters) Param[2]: centerY (type: int) Param[3]: radius (type: float) Param[4]: color (type: Color) -Function 233: DrawCircleLinesV() (3 input parameters) +Function 234: 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 234: DrawEllipse() (5 input parameters) +Function 235: DrawEllipse() (5 input parameters) Name: DrawEllipse Return type: void Description: Draw ellipse @@ -2297,7 +2303,7 @@ Function 234: DrawEllipse() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 235: DrawEllipseV() (4 input parameters) +Function 236: DrawEllipseV() (4 input parameters) Name: DrawEllipseV Return type: void Description: Draw ellipse (Vector version) @@ -2305,7 +2311,7 @@ Function 235: DrawEllipseV() (4 input parameters) Param[2]: radiusH (type: float) Param[3]: radiusV (type: float) Param[4]: color (type: Color) -Function 236: DrawEllipseLines() (5 input parameters) +Function 237: DrawEllipseLines() (5 input parameters) Name: DrawEllipseLines Return type: void Description: Draw ellipse outline @@ -2314,7 +2320,7 @@ Function 236: DrawEllipseLines() (5 input parameters) Param[3]: radiusH (type: float) Param[4]: radiusV (type: float) Param[5]: color (type: Color) -Function 237: DrawEllipseLinesV() (4 input parameters) +Function 238: DrawEllipseLinesV() (4 input parameters) Name: DrawEllipseLinesV Return type: void Description: Draw ellipse outline (Vector version) @@ -2322,7 +2328,7 @@ Function 237: DrawEllipseLinesV() (4 input parameters) Param[2]: radiusH (type: float) Param[3]: radiusV (type: float) Param[4]: color (type: Color) -Function 238: DrawRing() (7 input parameters) +Function 239: DrawRing() (7 input parameters) Name: DrawRing Return type: void Description: Draw ring @@ -2333,7 +2339,7 @@ Function 238: DrawRing() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 239: DrawRingLines() (7 input parameters) +Function 240: DrawRingLines() (7 input parameters) Name: DrawRingLines Return type: void Description: Draw ring outline @@ -2344,7 +2350,7 @@ Function 239: DrawRingLines() (7 input parameters) Param[5]: endAngle (type: float) Param[6]: segments (type: int) Param[7]: color (type: Color) -Function 240: DrawRectangle() (5 input parameters) +Function 241: DrawRectangle() (5 input parameters) Name: DrawRectangle Return type: void Description: Draw a color-filled rectangle @@ -2353,20 +2359,20 @@ Function 240: DrawRectangle() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 241: DrawRectangleV() (3 input parameters) +Function 242: 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 242: DrawRectangleRec() (2 input parameters) +Function 243: 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 243: DrawRectanglePro() (4 input parameters) +Function 244: DrawRectanglePro() (4 input parameters) Name: DrawRectanglePro Return type: void Description: Draw a color-filled rectangle with pro parameters @@ -2374,7 +2380,7 @@ Function 243: DrawRectanglePro() (4 input parameters) Param[2]: origin (type: Vector2) Param[3]: rotation (type: float) Param[4]: color (type: Color) -Function 244: DrawRectangleGradientV() (6 input parameters) +Function 245: DrawRectangleGradientV() (6 input parameters) Name: DrawRectangleGradientV Return type: void Description: Draw a vertical-gradient-filled rectangle @@ -2384,7 +2390,7 @@ Function 244: DrawRectangleGradientV() (6 input parameters) Param[4]: height (type: int) Param[5]: top (type: Color) Param[6]: bottom (type: Color) -Function 245: DrawRectangleGradientH() (6 input parameters) +Function 246: DrawRectangleGradientH() (6 input parameters) Name: DrawRectangleGradientH Return type: void Description: Draw a horizontal-gradient-filled rectangle @@ -2394,7 +2400,7 @@ Function 245: DrawRectangleGradientH() (6 input parameters) Param[4]: height (type: int) Param[5]: left (type: Color) Param[6]: right (type: Color) -Function 246: DrawRectangleGradientEx() (5 input parameters) +Function 247: DrawRectangleGradientEx() (5 input parameters) Name: DrawRectangleGradientEx Return type: void Description: Draw a gradient-filled rectangle with custom vertex colors @@ -2403,7 +2409,7 @@ Function 246: DrawRectangleGradientEx() (5 input parameters) Param[3]: bottomLeft (type: Color) Param[4]: bottomRight (type: Color) Param[5]: topRight (type: Color) -Function 247: DrawRectangleLines() (5 input parameters) +Function 248: DrawRectangleLines() (5 input parameters) Name: DrawRectangleLines Return type: void Description: Draw rectangle outline @@ -2412,14 +2418,14 @@ Function 247: DrawRectangleLines() (5 input parameters) Param[3]: width (type: int) Param[4]: height (type: int) Param[5]: color (type: Color) -Function 248: DrawRectangleLinesEx() (3 input parameters) +Function 249: 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 249: DrawRectangleRounded() (4 input parameters) +Function 250: DrawRectangleRounded() (4 input parameters) Name: DrawRectangleRounded Return type: void Description: Draw rectangle with rounded edges @@ -2427,7 +2433,7 @@ Function 249: DrawRectangleRounded() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 250: DrawRectangleRoundedLines() (4 input parameters) +Function 251: DrawRectangleRoundedLines() (4 input parameters) Name: DrawRectangleRoundedLines Return type: void Description: Draw rectangle lines with rounded edges @@ -2435,7 +2441,7 @@ Function 250: DrawRectangleRoundedLines() (4 input parameters) Param[2]: roundness (type: float) Param[3]: segments (type: int) Param[4]: color (type: Color) -Function 251: DrawRectangleRoundedLinesEx() (5 input parameters) +Function 252: DrawRectangleRoundedLinesEx() (5 input parameters) Name: DrawRectangleRoundedLinesEx Return type: void Description: Draw rectangle with rounded edges outline @@ -2444,7 +2450,7 @@ Function 251: DrawRectangleRoundedLinesEx() (5 input parameters) Param[3]: segments (type: int) Param[4]: lineThick (type: float) Param[5]: color (type: Color) -Function 252: DrawTriangle() (4 input parameters) +Function 253: DrawTriangle() (4 input parameters) Name: DrawTriangle Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -2452,7 +2458,7 @@ Function 252: DrawTriangle() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 253: DrawTriangleLines() (4 input parameters) +Function 254: DrawTriangleLines() (4 input parameters) Name: DrawTriangleLines Return type: void Description: Draw triangle outline (vertex in counter-clockwise order!) @@ -2460,21 +2466,21 @@ Function 253: DrawTriangleLines() (4 input parameters) Param[2]: v2 (type: Vector2) Param[3]: v3 (type: Vector2) Param[4]: color (type: Color) -Function 254: DrawTriangleFan() (3 input parameters) +Function 255: 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 255: DrawTriangleStrip() (3 input parameters) +Function 256: 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 256: DrawPoly() (5 input parameters) +Function 257: DrawPoly() (5 input parameters) Name: DrawPoly Return type: void Description: Draw a regular polygon (Vector version) @@ -2483,7 +2489,7 @@ Function 256: DrawPoly() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 257: DrawPolyLines() (5 input parameters) +Function 258: DrawPolyLines() (5 input parameters) Name: DrawPolyLines Return type: void Description: Draw a polygon outline of n sides @@ -2492,7 +2498,7 @@ Function 257: DrawPolyLines() (5 input parameters) Param[3]: radius (type: float) Param[4]: rotation (type: float) Param[5]: color (type: Color) -Function 258: DrawPolyLinesEx() (6 input parameters) +Function 259: DrawPolyLinesEx() (6 input parameters) Name: DrawPolyLinesEx Return type: void Description: Draw a polygon outline of n sides with extended parameters @@ -2502,7 +2508,7 @@ Function 258: DrawPolyLinesEx() (6 input parameters) Param[4]: rotation (type: float) Param[5]: lineThick (type: float) Param[6]: color (type: Color) -Function 259: DrawSplineLinear() (4 input parameters) +Function 260: DrawSplineLinear() (4 input parameters) Name: DrawSplineLinear Return type: void Description: Draw spline: Linear, minimum 2 points @@ -2510,7 +2516,7 @@ Function 259: DrawSplineLinear() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 260: DrawSplineBasis() (4 input parameters) +Function 261: DrawSplineBasis() (4 input parameters) Name: DrawSplineBasis Return type: void Description: Draw spline: B-Spline, minimum 4 points @@ -2518,7 +2524,7 @@ Function 260: DrawSplineBasis() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 261: DrawSplineCatmullRom() (4 input parameters) +Function 262: DrawSplineCatmullRom() (4 input parameters) Name: DrawSplineCatmullRom Return type: void Description: Draw spline: Catmull-Rom, minimum 4 points @@ -2526,7 +2532,7 @@ Function 261: DrawSplineCatmullRom() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 262: DrawSplineBezierQuadratic() (4 input parameters) +Function 263: DrawSplineBezierQuadratic() (4 input parameters) Name: DrawSplineBezierQuadratic Return type: void Description: Draw spline: Quadratic Bezier, minimum 3 points (1 control point): [p1, c2, p3, c4...] @@ -2534,7 +2540,7 @@ Function 262: DrawSplineBezierQuadratic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 263: DrawSplineBezierCubic() (4 input parameters) +Function 264: 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...] @@ -2542,7 +2548,7 @@ Function 263: DrawSplineBezierCubic() (4 input parameters) Param[2]: pointCount (type: int) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 264: DrawSplineSegmentLinear() (4 input parameters) +Function 265: DrawSplineSegmentLinear() (4 input parameters) Name: DrawSplineSegmentLinear Return type: void Description: Draw spline segment: Linear, 2 points @@ -2550,7 +2556,7 @@ Function 264: DrawSplineSegmentLinear() (4 input parameters) Param[2]: p2 (type: Vector2) Param[3]: thick (type: float) Param[4]: color (type: Color) -Function 265: DrawSplineSegmentBasis() (6 input parameters) +Function 266: DrawSplineSegmentBasis() (6 input parameters) Name: DrawSplineSegmentBasis Return type: void Description: Draw spline segment: B-Spline, 4 points @@ -2560,7 +2566,7 @@ Function 265: DrawSplineSegmentBasis() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 266: DrawSplineSegmentCatmullRom() (6 input parameters) +Function 267: DrawSplineSegmentCatmullRom() (6 input parameters) Name: DrawSplineSegmentCatmullRom Return type: void Description: Draw spline segment: Catmull-Rom, 4 points @@ -2570,7 +2576,7 @@ Function 266: DrawSplineSegmentCatmullRom() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 267: DrawSplineSegmentBezierQuadratic() (5 input parameters) +Function 268: DrawSplineSegmentBezierQuadratic() (5 input parameters) Name: DrawSplineSegmentBezierQuadratic Return type: void Description: Draw spline segment: Quadratic Bezier, 2 points, 1 control point @@ -2579,7 +2585,7 @@ Function 267: DrawSplineSegmentBezierQuadratic() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: thick (type: float) Param[5]: color (type: Color) -Function 268: DrawSplineSegmentBezierCubic() (6 input parameters) +Function 269: DrawSplineSegmentBezierCubic() (6 input parameters) Name: DrawSplineSegmentBezierCubic Return type: void Description: Draw spline segment: Cubic Bezier, 2 points, 2 control points @@ -2589,14 +2595,14 @@ Function 268: DrawSplineSegmentBezierCubic() (6 input parameters) Param[4]: p4 (type: Vector2) Param[5]: thick (type: float) Param[6]: color (type: Color) -Function 269: GetSplinePointLinear() (3 input parameters) +Function 270: 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 270: GetSplinePointBasis() (5 input parameters) +Function 271: GetSplinePointBasis() (5 input parameters) Name: GetSplinePointBasis Return type: Vector2 Description: Get (evaluate) spline point: B-Spline @@ -2605,7 +2611,7 @@ Function 270: GetSplinePointBasis() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 271: GetSplinePointCatmullRom() (5 input parameters) +Function 272: GetSplinePointCatmullRom() (5 input parameters) Name: GetSplinePointCatmullRom Return type: Vector2 Description: Get (evaluate) spline point: Catmull-Rom @@ -2614,7 +2620,7 @@ Function 271: GetSplinePointCatmullRom() (5 input parameters) Param[3]: p3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 272: GetSplinePointBezierQuad() (4 input parameters) +Function 273: GetSplinePointBezierQuad() (4 input parameters) Name: GetSplinePointBezierQuad Return type: Vector2 Description: Get (evaluate) spline point: Quadratic Bezier @@ -2622,7 +2628,7 @@ Function 272: GetSplinePointBezierQuad() (4 input parameters) Param[2]: c2 (type: Vector2) Param[3]: p3 (type: Vector2) Param[4]: t (type: float) -Function 273: GetSplinePointBezierCubic() (5 input parameters) +Function 274: GetSplinePointBezierCubic() (5 input parameters) Name: GetSplinePointBezierCubic Return type: Vector2 Description: Get (evaluate) spline point: Cubic Bezier @@ -2631,13 +2637,13 @@ Function 273: GetSplinePointBezierCubic() (5 input parameters) Param[3]: c3 (type: Vector2) Param[4]: p4 (type: Vector2) Param[5]: t (type: float) -Function 274: CheckCollisionRecs() (2 input parameters) +Function 275: 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 275: CheckCollisionCircles() (4 input parameters) +Function 276: CheckCollisionCircles() (4 input parameters) Name: CheckCollisionCircles Return type: bool Description: Check collision between two circles @@ -2645,14 +2651,14 @@ Function 275: CheckCollisionCircles() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector2) Param[4]: radius2 (type: float) -Function 276: CheckCollisionCircleRec() (3 input parameters) +Function 277: 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 277: CheckCollisionCircleLine() (4 input parameters) +Function 278: CheckCollisionCircleLine() (4 input parameters) Name: CheckCollisionCircleLine Return type: bool Description: Check if circle collides with a line created betweeen two points [p1] and [p2] @@ -2660,20 +2666,20 @@ Function 277: CheckCollisionCircleLine() (4 input parameters) Param[2]: radius (type: float) Param[3]: p1 (type: Vector2) Param[4]: p2 (type: Vector2) -Function 278: CheckCollisionPointRec() (2 input parameters) +Function 279: 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 279: CheckCollisionPointCircle() (3 input parameters) +Function 280: 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 280: CheckCollisionPointTriangle() (4 input parameters) +Function 281: CheckCollisionPointTriangle() (4 input parameters) Name: CheckCollisionPointTriangle Return type: bool Description: Check if point is inside a triangle @@ -2681,7 +2687,7 @@ Function 280: CheckCollisionPointTriangle() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: p3 (type: Vector2) -Function 281: CheckCollisionPointLine() (4 input parameters) +Function 282: 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] @@ -2689,14 +2695,14 @@ Function 281: CheckCollisionPointLine() (4 input parameters) Param[2]: p1 (type: Vector2) Param[3]: p2 (type: Vector2) Param[4]: threshold (type: int) -Function 282: CheckCollisionPointPoly() (3 input parameters) +Function 283: 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 283: CheckCollisionLines() (5 input parameters) +Function 284: 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 @@ -2705,18 +2711,18 @@ Function 283: CheckCollisionLines() (5 input parameters) Param[3]: startPos2 (type: Vector2) Param[4]: endPos2 (type: Vector2) Param[5]: collisionPoint (type: Vector2 *) -Function 284: GetCollisionRec() (2 input parameters) +Function 285: 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 285: LoadImage() (1 input parameters) +Function 286: 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 286: LoadImageRaw() (5 input parameters) +Function 287: LoadImageRaw() (5 input parameters) Name: LoadImageRaw Return type: Image Description: Load image from RAW file data @@ -2725,13 +2731,13 @@ Function 286: LoadImageRaw() (5 input parameters) Param[3]: height (type: int) Param[4]: format (type: int) Param[5]: headerSize (type: int) -Function 287: LoadImageAnim() (2 input parameters) +Function 288: 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 288: LoadImageAnimFromMemory() (4 input parameters) +Function 289: LoadImageAnimFromMemory() (4 input parameters) Name: LoadImageAnimFromMemory Return type: Image Description: Load image sequence from memory buffer @@ -2739,60 +2745,60 @@ Function 288: LoadImageAnimFromMemory() (4 input parameters) Param[2]: fileData (type: const unsigned char *) Param[3]: dataSize (type: int) Param[4]: frames (type: int *) -Function 289: LoadImageFromMemory() (3 input parameters) +Function 290: 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 290: LoadImageFromTexture() (1 input parameters) +Function 291: LoadImageFromTexture() (1 input parameters) Name: LoadImageFromTexture Return type: Image Description: Load image from GPU texture data Param[1]: texture (type: Texture2D) -Function 291: LoadImageFromScreen() (0 input parameters) +Function 292: LoadImageFromScreen() (0 input parameters) Name: LoadImageFromScreen Return type: Image Description: Load image from screen buffer and (screenshot) No input parameters -Function 292: IsImageValid() (1 input parameters) +Function 293: 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 293: UnloadImage() (1 input parameters) +Function 294: UnloadImage() (1 input parameters) Name: UnloadImage Return type: void Description: Unload image from CPU memory (RAM) Param[1]: image (type: Image) -Function 294: ExportImage() (2 input parameters) +Function 295: 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 295: ExportImageToMemory() (3 input parameters) +Function 296: 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 296: ExportImageAsCode() (2 input parameters) +Function 297: 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 297: GenImageColor() (3 input parameters) +Function 298: 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 298: GenImageGradientLinear() (5 input parameters) +Function 299: GenImageGradientLinear() (5 input parameters) Name: GenImageGradientLinear Return type: Image Description: Generate image: linear gradient, direction in degrees [0..360], 0=Vertical gradient @@ -2801,7 +2807,7 @@ Function 298: GenImageGradientLinear() (5 input parameters) Param[3]: direction (type: int) Param[4]: start (type: Color) Param[5]: end (type: Color) -Function 299: GenImageGradientRadial() (5 input parameters) +Function 300: GenImageGradientRadial() (5 input parameters) Name: GenImageGradientRadial Return type: Image Description: Generate image: radial gradient @@ -2810,7 +2816,7 @@ Function 299: GenImageGradientRadial() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 300: GenImageGradientSquare() (5 input parameters) +Function 301: GenImageGradientSquare() (5 input parameters) Name: GenImageGradientSquare Return type: Image Description: Generate image: square gradient @@ -2819,7 +2825,7 @@ Function 300: GenImageGradientSquare() (5 input parameters) Param[3]: density (type: float) Param[4]: inner (type: Color) Param[5]: outer (type: Color) -Function 301: GenImageChecked() (6 input parameters) +Function 302: GenImageChecked() (6 input parameters) Name: GenImageChecked Return type: Image Description: Generate image: checked @@ -2829,14 +2835,14 @@ Function 301: GenImageChecked() (6 input parameters) Param[4]: checksY (type: int) Param[5]: col1 (type: Color) Param[6]: col2 (type: Color) -Function 302: GenImageWhiteNoise() (3 input parameters) +Function 303: 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 303: GenImagePerlinNoise() (5 input parameters) +Function 304: GenImagePerlinNoise() (5 input parameters) Name: GenImagePerlinNoise Return type: Image Description: Generate image: perlin noise @@ -2845,45 +2851,45 @@ Function 303: GenImagePerlinNoise() (5 input parameters) Param[3]: offsetX (type: int) Param[4]: offsetY (type: int) Param[5]: scale (type: float) -Function 304: GenImageCellular() (3 input parameters) +Function 305: 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 305: GenImageText() (3 input parameters) +Function 306: 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 306: ImageCopy() (1 input parameters) +Function 307: ImageCopy() (1 input parameters) Name: ImageCopy Return type: Image Description: Create an image duplicate (useful for transformations) Param[1]: image (type: Image) -Function 307: ImageFromImage() (2 input parameters) +Function 308: 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 308: ImageFromChannel() (2 input parameters) +Function 309: 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 309: ImageText() (3 input parameters) +Function 310: 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 310: ImageTextEx() (5 input parameters) +Function 311: ImageTextEx() (5 input parameters) Name: ImageTextEx Return type: Image Description: Create an image from text (custom sprite font) @@ -2892,76 +2898,76 @@ Function 310: ImageTextEx() (5 input parameters) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) Param[5]: tint (type: Color) -Function 311: ImageFormat() (2 input parameters) +Function 312: 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 312: ImageToPOT() (2 input parameters) +Function 313: 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 313: ImageCrop() (2 input parameters) +Function 314: 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 314: ImageAlphaCrop() (2 input parameters) +Function 315: 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 315: ImageAlphaClear() (3 input parameters) +Function 316: 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 316: ImageAlphaMask() (2 input parameters) +Function 317: 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 317: ImageAlphaPremultiply() (1 input parameters) +Function 318: ImageAlphaPremultiply() (1 input parameters) Name: ImageAlphaPremultiply Return type: void Description: Premultiply alpha channel Param[1]: image (type: Image *) -Function 318: ImageBlurGaussian() (2 input parameters) +Function 319: 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 319: ImageKernelConvolution() (3 input parameters) +Function 320: 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 320: ImageResize() (3 input parameters) +Function 321: 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 321: ImageResizeNN() (3 input parameters) +Function 322: 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 322: ImageResizeCanvas() (6 input parameters) +Function 323: ImageResizeCanvas() (6 input parameters) Name: ImageResizeCanvas Return type: void Description: Resize canvas and fill with color @@ -2971,12 +2977,12 @@ Function 322: ImageResizeCanvas() (6 input parameters) Param[4]: offsetX (type: int) Param[5]: offsetY (type: int) Param[6]: fill (type: Color) -Function 323: ImageMipmaps() (1 input parameters) +Function 324: ImageMipmaps() (1 input parameters) Name: ImageMipmaps Return type: void Description: Compute all mipmap levels for a provided image Param[1]: image (type: Image *) -Function 324: ImageDither() (5 input parameters) +Function 325: ImageDither() (5 input parameters) Name: ImageDither Return type: void Description: Dither image data to 16bpp or lower (Floyd-Steinberg dithering) @@ -2985,109 +2991,109 @@ Function 324: ImageDither() (5 input parameters) Param[3]: gBpp (type: int) Param[4]: bBpp (type: int) Param[5]: aBpp (type: int) -Function 325: ImageFlipVertical() (1 input parameters) +Function 326: ImageFlipVertical() (1 input parameters) Name: ImageFlipVertical Return type: void Description: Flip image vertically Param[1]: image (type: Image *) -Function 326: ImageFlipHorizontal() (1 input parameters) +Function 327: ImageFlipHorizontal() (1 input parameters) Name: ImageFlipHorizontal Return type: void Description: Flip image horizontally Param[1]: image (type: Image *) -Function 327: ImageRotate() (2 input parameters) +Function 328: 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 328: ImageRotateCW() (1 input parameters) +Function 329: ImageRotateCW() (1 input parameters) Name: ImageRotateCW Return type: void Description: Rotate image clockwise 90deg Param[1]: image (type: Image *) -Function 329: ImageRotateCCW() (1 input parameters) +Function 330: ImageRotateCCW() (1 input parameters) Name: ImageRotateCCW Return type: void Description: Rotate image counter-clockwise 90deg Param[1]: image (type: Image *) -Function 330: ImageColorTint() (2 input parameters) +Function 331: 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 331: ImageColorInvert() (1 input parameters) +Function 332: ImageColorInvert() (1 input parameters) Name: ImageColorInvert Return type: void Description: Modify image color: invert Param[1]: image (type: Image *) -Function 332: ImageColorGrayscale() (1 input parameters) +Function 333: ImageColorGrayscale() (1 input parameters) Name: ImageColorGrayscale Return type: void Description: Modify image color: grayscale Param[1]: image (type: Image *) -Function 333: ImageColorContrast() (2 input parameters) +Function 334: 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 334: ImageColorBrightness() (2 input parameters) +Function 335: 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 335: ImageColorReplace() (3 input parameters) +Function 336: 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 336: LoadImageColors() (1 input parameters) +Function 337: 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 337: LoadImagePalette() (3 input parameters) +Function 338: 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 338: UnloadImageColors() (1 input parameters) +Function 339: UnloadImageColors() (1 input parameters) Name: UnloadImageColors Return type: void Description: Unload color data loaded with LoadImageColors() Param[1]: colors (type: Color *) -Function 339: UnloadImagePalette() (1 input parameters) +Function 340: UnloadImagePalette() (1 input parameters) Name: UnloadImagePalette Return type: void Description: Unload colors palette loaded with LoadImagePalette() Param[1]: colors (type: Color *) -Function 340: GetImageAlphaBorder() (2 input parameters) +Function 341: 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 341: GetImageColor() (3 input parameters) +Function 342: 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 342: ImageClearBackground() (2 input parameters) +Function 343: 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 343: ImageDrawPixel() (4 input parameters) +Function 344: ImageDrawPixel() (4 input parameters) Name: ImageDrawPixel Return type: void Description: Draw pixel within an image @@ -3095,14 +3101,14 @@ Function 343: ImageDrawPixel() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: color (type: Color) -Function 344: ImageDrawPixelV() (3 input parameters) +Function 345: 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 345: ImageDrawLine() (6 input parameters) +Function 346: ImageDrawLine() (6 input parameters) Name: ImageDrawLine Return type: void Description: Draw line within an image @@ -3112,7 +3118,7 @@ Function 345: ImageDrawLine() (6 input parameters) Param[4]: endPosX (type: int) Param[5]: endPosY (type: int) Param[6]: color (type: Color) -Function 346: ImageDrawLineV() (4 input parameters) +Function 347: ImageDrawLineV() (4 input parameters) Name: ImageDrawLineV Return type: void Description: Draw line within an image (Vector version) @@ -3120,7 +3126,7 @@ Function 346: ImageDrawLineV() (4 input parameters) Param[2]: start (type: Vector2) Param[3]: end (type: Vector2) Param[4]: color (type: Color) -Function 347: ImageDrawLineEx() (5 input parameters) +Function 348: ImageDrawLineEx() (5 input parameters) Name: ImageDrawLineEx Return type: void Description: Draw a line defining thickness within an image @@ -3129,7 +3135,7 @@ Function 347: ImageDrawLineEx() (5 input parameters) Param[3]: end (type: Vector2) Param[4]: thick (type: int) Param[5]: color (type: Color) -Function 348: ImageDrawCircle() (5 input parameters) +Function 349: ImageDrawCircle() (5 input parameters) Name: ImageDrawCircle Return type: void Description: Draw a filled circle within an image @@ -3138,7 +3144,7 @@ Function 348: ImageDrawCircle() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 349: ImageDrawCircleV() (4 input parameters) +Function 350: ImageDrawCircleV() (4 input parameters) Name: ImageDrawCircleV Return type: void Description: Draw a filled circle within an image (Vector version) @@ -3146,7 +3152,7 @@ Function 349: ImageDrawCircleV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 350: ImageDrawCircleLines() (5 input parameters) +Function 351: ImageDrawCircleLines() (5 input parameters) Name: ImageDrawCircleLines Return type: void Description: Draw circle outline within an image @@ -3155,7 +3161,7 @@ Function 350: ImageDrawCircleLines() (5 input parameters) Param[3]: centerY (type: int) Param[4]: radius (type: int) Param[5]: color (type: Color) -Function 351: ImageDrawCircleLinesV() (4 input parameters) +Function 352: ImageDrawCircleLinesV() (4 input parameters) Name: ImageDrawCircleLinesV Return type: void Description: Draw circle outline within an image (Vector version) @@ -3163,7 +3169,7 @@ Function 351: ImageDrawCircleLinesV() (4 input parameters) Param[2]: center (type: Vector2) Param[3]: radius (type: int) Param[4]: color (type: Color) -Function 352: ImageDrawRectangle() (6 input parameters) +Function 353: ImageDrawRectangle() (6 input parameters) Name: ImageDrawRectangle Return type: void Description: Draw rectangle within an image @@ -3173,7 +3179,7 @@ Function 352: ImageDrawRectangle() (6 input parameters) Param[4]: width (type: int) Param[5]: height (type: int) Param[6]: color (type: Color) -Function 353: ImageDrawRectangleV() (4 input parameters) +Function 354: ImageDrawRectangleV() (4 input parameters) Name: ImageDrawRectangleV Return type: void Description: Draw rectangle within an image (Vector version) @@ -3181,14 +3187,14 @@ Function 353: ImageDrawRectangleV() (4 input parameters) Param[2]: position (type: Vector2) Param[3]: size (type: Vector2) Param[4]: color (type: Color) -Function 354: ImageDrawRectangleRec() (3 input parameters) +Function 355: 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 355: ImageDrawRectangleLines() (4 input parameters) +Function 356: ImageDrawRectangleLines() (4 input parameters) Name: ImageDrawRectangleLines Return type: void Description: Draw rectangle lines within an image @@ -3196,7 +3202,7 @@ Function 355: ImageDrawRectangleLines() (4 input parameters) Param[2]: rec (type: Rectangle) Param[3]: thick (type: int) Param[4]: color (type: Color) -Function 356: ImageDrawTriangle() (5 input parameters) +Function 357: ImageDrawTriangle() (5 input parameters) Name: ImageDrawTriangle Return type: void Description: Draw triangle within an image @@ -3205,7 +3211,7 @@ Function 356: ImageDrawTriangle() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 357: ImageDrawTriangleEx() (7 input parameters) +Function 358: ImageDrawTriangleEx() (7 input parameters) Name: ImageDrawTriangleEx Return type: void Description: Draw triangle with interpolated colors within an image @@ -3216,7 +3222,7 @@ Function 357: ImageDrawTriangleEx() (7 input parameters) Param[5]: c1 (type: Color) Param[6]: c2 (type: Color) Param[7]: c3 (type: Color) -Function 358: ImageDrawTriangleLines() (5 input parameters) +Function 359: ImageDrawTriangleLines() (5 input parameters) Name: ImageDrawTriangleLines Return type: void Description: Draw triangle outline within an image @@ -3225,7 +3231,7 @@ Function 358: ImageDrawTriangleLines() (5 input parameters) Param[3]: v2 (type: Vector2) Param[4]: v3 (type: Vector2) Param[5]: color (type: Color) -Function 359: ImageDrawTriangleFan() (4 input parameters) +Function 360: 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) @@ -3233,7 +3239,7 @@ Function 359: ImageDrawTriangleFan() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 360: ImageDrawTriangleStrip() (4 input parameters) +Function 361: ImageDrawTriangleStrip() (4 input parameters) Name: ImageDrawTriangleStrip Return type: void Description: Draw a triangle strip defined by points within an image @@ -3241,7 +3247,7 @@ Function 360: ImageDrawTriangleStrip() (4 input parameters) Param[2]: points (type: const Vector2 *) Param[3]: pointCount (type: int) Param[4]: color (type: Color) -Function 361: ImageDraw() (5 input parameters) +Function 362: ImageDraw() (5 input parameters) Name: ImageDraw Return type: void Description: Draw a source image within a destination image (tint applied to source) @@ -3250,7 +3256,7 @@ Function 361: ImageDraw() (5 input parameters) Param[3]: srcRec (type: Rectangle) Param[4]: dstRec (type: Rectangle) Param[5]: tint (type: Color) -Function 362: ImageDrawText() (6 input parameters) +Function 363: ImageDrawText() (6 input parameters) Name: ImageDrawText Return type: void Description: Draw text (using default font) within an image (destination) @@ -3260,7 +3266,7 @@ Function 362: ImageDrawText() (6 input parameters) Param[4]: posY (type: int) Param[5]: fontSize (type: int) Param[6]: color (type: Color) -Function 363: ImageDrawTextEx() (7 input parameters) +Function 364: ImageDrawTextEx() (7 input parameters) Name: ImageDrawTextEx Return type: void Description: Draw text (custom sprite font) within an image (destination) @@ -3271,79 +3277,79 @@ Function 363: ImageDrawTextEx() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 364: LoadTexture() (1 input parameters) +Function 365: 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 365: LoadTextureFromImage() (1 input parameters) +Function 366: LoadTextureFromImage() (1 input parameters) Name: LoadTextureFromImage Return type: Texture2D Description: Load texture from image data Param[1]: image (type: Image) -Function 366: LoadTextureCubemap() (2 input parameters) +Function 367: 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 367: LoadRenderTexture() (2 input parameters) +Function 368: 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 368: IsTextureValid() (1 input parameters) +Function 369: 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 369: UnloadTexture() (1 input parameters) +Function 370: UnloadTexture() (1 input parameters) Name: UnloadTexture Return type: void Description: Unload texture from GPU memory (VRAM) Param[1]: texture (type: Texture2D) -Function 370: IsRenderTextureValid() (1 input parameters) +Function 371: 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 371: UnloadRenderTexture() (1 input parameters) +Function 372: UnloadRenderTexture() (1 input parameters) Name: UnloadRenderTexture Return type: void Description: Unload render texture from GPU memory (VRAM) Param[1]: target (type: RenderTexture2D) -Function 372: UpdateTexture() (2 input parameters) +Function 373: UpdateTexture() (2 input parameters) Name: UpdateTexture Return type: void Description: Update GPU texture with new data (pixels should be able to fill texture) Param[1]: texture (type: Texture2D) Param[2]: pixels (type: const void *) -Function 373: UpdateTextureRec() (3 input parameters) +Function 374: UpdateTextureRec() (3 input parameters) Name: UpdateTextureRec Return type: void Description: Update GPU texture rectangle with new data (pixels and rec should fit in texture) Param[1]: texture (type: Texture2D) Param[2]: rec (type: Rectangle) Param[3]: pixels (type: const void *) -Function 374: GenTextureMipmaps() (1 input parameters) +Function 375: GenTextureMipmaps() (1 input parameters) Name: GenTextureMipmaps Return type: void Description: Generate GPU mipmaps for a texture Param[1]: texture (type: Texture2D *) -Function 375: SetTextureFilter() (2 input parameters) +Function 376: 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 376: SetTextureWrap() (2 input parameters) +Function 377: 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 377: DrawTexture() (4 input parameters) +Function 378: DrawTexture() (4 input parameters) Name: DrawTexture Return type: void Description: Draw a Texture2D @@ -3351,14 +3357,14 @@ Function 377: DrawTexture() (4 input parameters) Param[2]: posX (type: int) Param[3]: posY (type: int) Param[4]: tint (type: Color) -Function 378: DrawTextureV() (3 input parameters) +Function 379: 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 379: DrawTextureEx() (5 input parameters) +Function 380: DrawTextureEx() (5 input parameters) Name: DrawTextureEx Return type: void Description: Draw a Texture2D with extended parameters @@ -3367,7 +3373,7 @@ Function 379: DrawTextureEx() (5 input parameters) Param[3]: rotation (type: float) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 380: DrawTextureRec() (4 input parameters) +Function 381: DrawTextureRec() (4 input parameters) Name: DrawTextureRec Return type: void Description: Draw a part of a texture defined by a rectangle @@ -3375,7 +3381,7 @@ Function 380: DrawTextureRec() (4 input parameters) Param[2]: source (type: Rectangle) Param[3]: position (type: Vector2) Param[4]: tint (type: Color) -Function 381: DrawTexturePro() (6 input parameters) +Function 382: DrawTexturePro() (6 input parameters) Name: DrawTexturePro Return type: void Description: Draw a part of a texture defined by a rectangle with 'pro' parameters @@ -3385,7 +3391,7 @@ Function 381: DrawTexturePro() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 382: DrawTextureNPatch() (6 input parameters) +Function 383: DrawTextureNPatch() (6 input parameters) Name: DrawTextureNPatch Return type: void Description: Draws a texture (or part of it) that stretches or shrinks nicely @@ -3395,119 +3401,119 @@ Function 382: DrawTextureNPatch() (6 input parameters) Param[4]: origin (type: Vector2) Param[5]: rotation (type: float) Param[6]: tint (type: Color) -Function 383: ColorIsEqual() (2 input parameters) +Function 384: 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 384: Fade() (2 input parameters) +Function 385: 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 385: ColorToInt() (1 input parameters) +Function 386: ColorToInt() (1 input parameters) Name: ColorToInt Return type: int Description: Get hexadecimal value for a Color (0xRRGGBBAA) Param[1]: color (type: Color) -Function 386: ColorNormalize() (1 input parameters) +Function 387: ColorNormalize() (1 input parameters) Name: ColorNormalize Return type: Vector4 Description: Get Color normalized as float [0..1] Param[1]: color (type: Color) -Function 387: ColorFromNormalized() (1 input parameters) +Function 388: ColorFromNormalized() (1 input parameters) Name: ColorFromNormalized Return type: Color Description: Get Color from normalized values [0..1] Param[1]: normalized (type: Vector4) -Function 388: ColorToHSV() (1 input parameters) +Function 389: 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 389: ColorFromHSV() (3 input parameters) +Function 390: 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 390: ColorTint() (2 input parameters) +Function 391: 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 391: ColorBrightness() (2 input parameters) +Function 392: 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 392: ColorContrast() (2 input parameters) +Function 393: 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 393: ColorAlpha() (2 input parameters) +Function 394: 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 394: ColorAlphaBlend() (3 input parameters) +Function 395: 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 395: ColorLerp() (3 input parameters) +Function 396: 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 396: GetColor() (1 input parameters) +Function 397: GetColor() (1 input parameters) Name: GetColor Return type: Color Description: Get Color structure from hexadecimal value Param[1]: hexValue (type: unsigned int) -Function 397: GetPixelColor() (2 input parameters) +Function 398: 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 398: SetPixelColor() (3 input parameters) +Function 399: 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 399: GetPixelDataSize() (3 input parameters) +Function 400: 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 400: GetFontDefault() (0 input parameters) +Function 401: GetFontDefault() (0 input parameters) Name: GetFontDefault Return type: Font Description: Get the default Font No input parameters -Function 401: LoadFont() (1 input parameters) +Function 402: 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 402: LoadFontEx() (4 input parameters) +Function 403: 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 @@ -3515,14 +3521,14 @@ Function 402: LoadFontEx() (4 input parameters) Param[2]: fontSize (type: int) Param[3]: codepoints (type: const int *) Param[4]: codepointCount (type: int) -Function 403: LoadFontFromImage() (3 input parameters) +Function 404: 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 404: LoadFontFromMemory() (6 input parameters) +Function 405: LoadFontFromMemory() (6 input parameters) Name: LoadFontFromMemory Return type: Font Description: Load font from memory buffer, fileType refers to extension: i.e. '.ttf' @@ -3532,12 +3538,12 @@ Function 404: LoadFontFromMemory() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: codepoints (type: const int *) Param[6]: codepointCount (type: int) -Function 405: IsFontValid() (1 input parameters) +Function 406: 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 406: LoadFontData() (7 input parameters) +Function 407: LoadFontData() (7 input parameters) Name: LoadFontData Return type: GlyphInfo * Description: Load font data for further use @@ -3548,7 +3554,7 @@ Function 406: LoadFontData() (7 input parameters) Param[5]: codepointCount (type: int) Param[6]: type (type: int) Param[7]: glyphCount (type: int *) -Function 407: GenImageFontAtlas() (6 input parameters) +Function 408: GenImageFontAtlas() (6 input parameters) Name: GenImageFontAtlas Return type: Image Description: Generate image font atlas using chars info @@ -3558,30 +3564,30 @@ Function 407: GenImageFontAtlas() (6 input parameters) Param[4]: fontSize (type: int) Param[5]: padding (type: int) Param[6]: packMethod (type: int) -Function 408: UnloadFontData() (2 input parameters) +Function 409: 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 409: UnloadFont() (1 input parameters) +Function 410: UnloadFont() (1 input parameters) Name: UnloadFont Return type: void Description: Unload font from GPU memory (VRAM) Param[1]: font (type: Font) -Function 410: ExportFontAsCode() (2 input parameters) +Function 411: 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 411: DrawFPS() (2 input parameters) +Function 412: DrawFPS() (2 input parameters) Name: DrawFPS Return type: void Description: Draw current FPS Param[1]: posX (type: int) Param[2]: posY (type: int) -Function 412: DrawText() (5 input parameters) +Function 413: DrawText() (5 input parameters) Name: DrawText Return type: void Description: Draw text (using default font) @@ -3590,7 +3596,7 @@ Function 412: DrawText() (5 input parameters) Param[3]: posY (type: int) Param[4]: fontSize (type: int) Param[5]: color (type: Color) -Function 413: DrawTextEx() (6 input parameters) +Function 414: DrawTextEx() (6 input parameters) Name: DrawTextEx Return type: void Description: Draw text using font and additional parameters @@ -3600,7 +3606,7 @@ Function 413: DrawTextEx() (6 input parameters) Param[4]: fontSize (type: float) Param[5]: spacing (type: float) Param[6]: tint (type: Color) -Function 414: DrawTextPro() (8 input parameters) +Function 415: DrawTextPro() (8 input parameters) Name: DrawTextPro Return type: void Description: Draw text using Font and pro parameters (rotation) @@ -3612,7 +3618,7 @@ Function 414: DrawTextPro() (8 input parameters) Param[6]: fontSize (type: float) Param[7]: spacing (type: float) Param[8]: tint (type: Color) -Function 415: DrawTextCodepoint() (5 input parameters) +Function 416: DrawTextCodepoint() (5 input parameters) Name: DrawTextCodepoint Return type: void Description: Draw one character (codepoint) @@ -3621,7 +3627,7 @@ Function 415: DrawTextCodepoint() (5 input parameters) Param[3]: position (type: Vector2) Param[4]: fontSize (type: float) Param[5]: tint (type: Color) -Function 416: DrawTextCodepoints() (7 input parameters) +Function 417: DrawTextCodepoints() (7 input parameters) Name: DrawTextCodepoints Return type: void Description: Draw multiple character (codepoint) @@ -3632,18 +3638,18 @@ Function 416: DrawTextCodepoints() (7 input parameters) Param[5]: fontSize (type: float) Param[6]: spacing (type: float) Param[7]: tint (type: Color) -Function 417: SetTextLineSpacing() (1 input parameters) +Function 418: 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 418: MeasureText() (2 input parameters) +Function 419: 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 419: MeasureTextEx() (4 input parameters) +Function 420: MeasureTextEx() (4 input parameters) Name: MeasureTextEx Return type: Vector2 Description: Measure string size for Font @@ -3651,137 +3657,137 @@ Function 419: MeasureTextEx() (4 input parameters) Param[2]: text (type: const char *) Param[3]: fontSize (type: float) Param[4]: spacing (type: float) -Function 420: GetGlyphIndex() (2 input parameters) +Function 421: 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 421: GetGlyphInfo() (2 input parameters) +Function 422: 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 422: GetGlyphAtlasRec() (2 input parameters) +Function 423: 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 423: LoadUTF8() (2 input parameters) +Function 424: 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 424: UnloadUTF8() (1 input parameters) +Function 425: UnloadUTF8() (1 input parameters) Name: UnloadUTF8 Return type: void Description: Unload UTF-8 text encoded from codepoints array Param[1]: text (type: char *) -Function 425: LoadCodepoints() (2 input parameters) +Function 426: 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 426: UnloadCodepoints() (1 input parameters) +Function 427: UnloadCodepoints() (1 input parameters) Name: UnloadCodepoints Return type: void Description: Unload codepoints data from memory Param[1]: codepoints (type: int *) -Function 427: GetCodepointCount() (1 input parameters) +Function 428: 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 428: GetCodepoint() (2 input parameters) +Function 429: 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 429: GetCodepointNext() (2 input parameters) +Function 430: 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 430: GetCodepointPrevious() (2 input parameters) +Function 431: 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 431: CodepointToUTF8() (2 input parameters) +Function 432: 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 432: LoadTextLines() (2 input parameters) +Function 433: LoadTextLines() (2 input parameters) Name: LoadTextLines Return type: char ** Description: Load text as separate lines ('\n') Param[1]: text (type: const char *) Param[2]: count (type: int *) -Function 433: UnloadTextLines() (2 input parameters) +Function 434: UnloadTextLines() (2 input parameters) Name: UnloadTextLines Return type: void Description: Unload text lines Param[1]: text (type: char **) Param[2]: lineCount (type: int) -Function 434: TextCopy() (2 input parameters) +Function 435: 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 435: TextIsEqual() (2 input parameters) +Function 436: 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 436: TextLength() (1 input parameters) +Function 437: 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 437: TextFormat() (2 input parameters) +Function 438: 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 438: TextSubtext() (3 input parameters) +Function 439: 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 439: TextRemoveSpaces() (1 input parameters) +Function 440: TextRemoveSpaces() (1 input parameters) Name: TextRemoveSpaces Return type: const char * Description: Remove text spaces, concat words Param[1]: text (type: const char *) -Function 440: GetTextBetween() (3 input parameters) +Function 441: GetTextBetween() (3 input parameters) Name: GetTextBetween Return type: char * Description: Get text between two strings Param[1]: text (type: const char *) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) -Function 441: TextReplace() (3 input parameters) +Function 442: 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]: search (type: const char *) Param[3]: replacement (type: const char *) -Function 442: TextReplaceBetween() (4 input parameters) +Function 443: TextReplaceBetween() (4 input parameters) Name: TextReplaceBetween Return type: char * Description: Replace text between two specific strings (WARNING: memory must be freed!) @@ -3789,89 +3795,89 @@ Function 442: TextReplaceBetween() (4 input parameters) Param[2]: begin (type: const char *) Param[3]: end (type: const char *) Param[4]: replacement (type: const char *) -Function 443: TextInsert() (3 input parameters) +Function 444: 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 444: TextJoin() (3 input parameters) +Function 445: TextJoin() (3 input parameters) Name: TextJoin Return type: char * Description: Join text strings with delimiter Param[1]: textList (type: char **) Param[2]: count (type: int) Param[3]: delimiter (type: const char *) -Function 445: TextSplit() (3 input parameters) +Function 446: TextSplit() (3 input parameters) Name: TextSplit Return type: char ** Description: Split text into multiple strings, using MAX_TEXTSPLIT_COUNT static strings Param[1]: text (type: const char *) Param[2]: delimiter (type: char) Param[3]: count (type: int *) -Function 446: TextAppend() (3 input parameters) +Function 447: 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 447: TextFindIndex() (2 input parameters) +Function 448: TextFindIndex() (2 input parameters) Name: TextFindIndex Return type: int Description: Find first text occurrence within a string, -1 if not found Param[1]: text (type: const char *) Param[2]: search (type: const char *) -Function 448: TextToUpper() (1 input parameters) +Function 449: TextToUpper() (1 input parameters) Name: TextToUpper Return type: char * Description: Get upper case version of provided string Param[1]: text (type: const char *) -Function 449: TextToLower() (1 input parameters) +Function 450: TextToLower() (1 input parameters) Name: TextToLower Return type: char * Description: Get lower case version of provided string Param[1]: text (type: const char *) -Function 450: TextToPascal() (1 input parameters) +Function 451: TextToPascal() (1 input parameters) Name: TextToPascal Return type: char * Description: Get Pascal case notation version of provided string Param[1]: text (type: const char *) -Function 451: TextToSnake() (1 input parameters) +Function 452: TextToSnake() (1 input parameters) Name: TextToSnake Return type: char * Description: Get Snake case notation version of provided string Param[1]: text (type: const char *) -Function 452: TextToCamel() (1 input parameters) +Function 453: TextToCamel() (1 input parameters) Name: TextToCamel Return type: char * Description: Get Camel case notation version of provided string Param[1]: text (type: const char *) -Function 453: TextToInteger() (1 input parameters) +Function 454: TextToInteger() (1 input parameters) Name: TextToInteger Return type: int Description: Get integer value from text Param[1]: text (type: const char *) -Function 454: TextToFloat() (1 input parameters) +Function 455: TextToFloat() (1 input parameters) Name: TextToFloat Return type: float Description: Get float value from text Param[1]: text (type: const char *) -Function 455: DrawLine3D() (3 input parameters) +Function 456: 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 456: DrawPoint3D() (2 input parameters) +Function 457: 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 457: DrawCircle3D() (5 input parameters) +Function 458: DrawCircle3D() (5 input parameters) Name: DrawCircle3D Return type: void Description: Draw a circle in 3D world space @@ -3880,7 +3886,7 @@ Function 457: DrawCircle3D() (5 input parameters) Param[3]: rotationAxis (type: Vector3) Param[4]: rotationAngle (type: float) Param[5]: color (type: Color) -Function 458: DrawTriangle3D() (4 input parameters) +Function 459: DrawTriangle3D() (4 input parameters) Name: DrawTriangle3D Return type: void Description: Draw a color-filled triangle (vertex in counter-clockwise order!) @@ -3888,14 +3894,14 @@ Function 458: DrawTriangle3D() (4 input parameters) Param[2]: v2 (type: Vector3) Param[3]: v3 (type: Vector3) Param[4]: color (type: Color) -Function 459: DrawTriangleStrip3D() (3 input parameters) +Function 460: 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 460: DrawCube() (5 input parameters) +Function 461: DrawCube() (5 input parameters) Name: DrawCube Return type: void Description: Draw cube @@ -3904,14 +3910,14 @@ Function 460: DrawCube() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 461: DrawCubeV() (3 input parameters) +Function 462: 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 462: DrawCubeWires() (5 input parameters) +Function 463: DrawCubeWires() (5 input parameters) Name: DrawCubeWires Return type: void Description: Draw cube wires @@ -3920,21 +3926,21 @@ Function 462: DrawCubeWires() (5 input parameters) Param[3]: height (type: float) Param[4]: length (type: float) Param[5]: color (type: Color) -Function 463: DrawCubeWiresV() (3 input parameters) +Function 464: 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 464: DrawSphere() (3 input parameters) +Function 465: 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 465: DrawSphereEx() (5 input parameters) +Function 466: DrawSphereEx() (5 input parameters) Name: DrawSphereEx Return type: void Description: Draw sphere with extended parameters @@ -3943,7 +3949,7 @@ Function 465: DrawSphereEx() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 466: DrawSphereWires() (5 input parameters) +Function 467: DrawSphereWires() (5 input parameters) Name: DrawSphereWires Return type: void Description: Draw sphere wires @@ -3952,7 +3958,7 @@ Function 466: DrawSphereWires() (5 input parameters) Param[3]: rings (type: int) Param[4]: slices (type: int) Param[5]: color (type: Color) -Function 467: DrawCylinder() (6 input parameters) +Function 468: DrawCylinder() (6 input parameters) Name: DrawCylinder Return type: void Description: Draw a cylinder/cone @@ -3962,7 +3968,7 @@ Function 467: DrawCylinder() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 468: DrawCylinderEx() (6 input parameters) +Function 469: DrawCylinderEx() (6 input parameters) Name: DrawCylinderEx Return type: void Description: Draw a cylinder with base at startPos and top at endPos @@ -3972,7 +3978,7 @@ Function 468: DrawCylinderEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 469: DrawCylinderWires() (6 input parameters) +Function 470: DrawCylinderWires() (6 input parameters) Name: DrawCylinderWires Return type: void Description: Draw a cylinder/cone wires @@ -3982,7 +3988,7 @@ Function 469: DrawCylinderWires() (6 input parameters) Param[4]: height (type: float) Param[5]: slices (type: int) Param[6]: color (type: Color) -Function 470: DrawCylinderWiresEx() (6 input parameters) +Function 471: DrawCylinderWiresEx() (6 input parameters) Name: DrawCylinderWiresEx Return type: void Description: Draw a cylinder wires with base at startPos and top at endPos @@ -3992,7 +3998,7 @@ Function 470: DrawCylinderWiresEx() (6 input parameters) Param[4]: endRadius (type: float) Param[5]: sides (type: int) Param[6]: color (type: Color) -Function 471: DrawCapsule() (6 input parameters) +Function 472: DrawCapsule() (6 input parameters) Name: DrawCapsule Return type: void Description: Draw a capsule with the center of its sphere caps at startPos and endPos @@ -4002,7 +4008,7 @@ Function 471: DrawCapsule() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 472: DrawCapsuleWires() (6 input parameters) +Function 473: DrawCapsuleWires() (6 input parameters) Name: DrawCapsuleWires Return type: void Description: Draw capsule wireframe with the center of its sphere caps at startPos and endPos @@ -4012,51 +4018,51 @@ Function 472: DrawCapsuleWires() (6 input parameters) Param[4]: slices (type: int) Param[5]: rings (type: int) Param[6]: color (type: Color) -Function 473: DrawPlane() (3 input parameters) +Function 474: 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 474: DrawRay() (2 input parameters) +Function 475: 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 475: DrawGrid() (2 input parameters) +Function 476: 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 476: LoadModel() (1 input parameters) +Function 477: LoadModel() (1 input parameters) Name: LoadModel Return type: Model Description: Load model from files (meshes and materials) Param[1]: fileName (type: const char *) -Function 477: LoadModelFromMesh() (1 input parameters) +Function 478: LoadModelFromMesh() (1 input parameters) Name: LoadModelFromMesh Return type: Model Description: Load model from generated mesh (default material) Param[1]: mesh (type: Mesh) -Function 478: IsModelValid() (1 input parameters) +Function 479: 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 479: UnloadModel() (1 input parameters) +Function 480: 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 480: GetModelBoundingBox() (1 input parameters) +Function 481: GetModelBoundingBox() (1 input parameters) Name: GetModelBoundingBox Return type: BoundingBox Description: Compute model bounding box limits (considers all meshes) Param[1]: model (type: Model) -Function 481: DrawModel() (4 input parameters) +Function 482: DrawModel() (4 input parameters) Name: DrawModel Return type: void Description: Draw a model (with texture if set) @@ -4064,7 +4070,7 @@ Function 481: DrawModel() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 482: DrawModelEx() (6 input parameters) +Function 483: DrawModelEx() (6 input parameters) Name: DrawModelEx Return type: void Description: Draw a model with extended parameters @@ -4074,7 +4080,7 @@ Function 482: DrawModelEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 483: DrawModelWires() (4 input parameters) +Function 484: DrawModelWires() (4 input parameters) Name: DrawModelWires Return type: void Description: Draw a model wires (with texture if set) @@ -4082,7 +4088,7 @@ Function 483: DrawModelWires() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 484: DrawModelWiresEx() (6 input parameters) +Function 485: DrawModelWiresEx() (6 input parameters) Name: DrawModelWiresEx Return type: void Description: Draw a model wires (with texture if set) with extended parameters @@ -4092,7 +4098,7 @@ Function 484: DrawModelWiresEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 485: DrawModelPoints() (4 input parameters) +Function 486: DrawModelPoints() (4 input parameters) Name: DrawModelPoints Return type: void Description: Draw a model as points @@ -4100,7 +4106,7 @@ Function 485: DrawModelPoints() (4 input parameters) Param[2]: position (type: Vector3) Param[3]: scale (type: float) Param[4]: tint (type: Color) -Function 486: DrawModelPointsEx() (6 input parameters) +Function 487: DrawModelPointsEx() (6 input parameters) Name: DrawModelPointsEx Return type: void Description: Draw a model as points with extended parameters @@ -4110,13 +4116,13 @@ Function 486: DrawModelPointsEx() (6 input parameters) Param[4]: rotationAngle (type: float) Param[5]: scale (type: Vector3) Param[6]: tint (type: Color) -Function 487: DrawBoundingBox() (2 input parameters) +Function 488: 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 488: DrawBillboard() (5 input parameters) +Function 489: DrawBillboard() (5 input parameters) Name: DrawBillboard Return type: void Description: Draw a billboard texture @@ -4125,7 +4131,7 @@ Function 488: DrawBillboard() (5 input parameters) Param[3]: position (type: Vector3) Param[4]: scale (type: float) Param[5]: tint (type: Color) -Function 489: DrawBillboardRec() (6 input parameters) +Function 490: DrawBillboardRec() (6 input parameters) Name: DrawBillboardRec Return type: void Description: Draw a billboard texture defined by source @@ -4135,7 +4141,7 @@ Function 489: DrawBillboardRec() (6 input parameters) Param[4]: position (type: Vector3) Param[5]: size (type: Vector2) Param[6]: tint (type: Color) -Function 490: DrawBillboardPro() (9 input parameters) +Function 491: DrawBillboardPro() (9 input parameters) Name: DrawBillboardPro Return type: void Description: Draw a billboard texture defined by source and rotation @@ -4148,13 +4154,13 @@ Function 490: DrawBillboardPro() (9 input parameters) Param[7]: origin (type: Vector2) Param[8]: rotation (type: float) Param[9]: tint (type: Color) -Function 491: UploadMesh() (2 input parameters) +Function 492: 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 492: UpdateMeshBuffer() (5 input parameters) +Function 493: UpdateMeshBuffer() (5 input parameters) Name: UpdateMeshBuffer Return type: void Description: Update mesh vertex data in GPU for a specific buffer index @@ -4163,19 +4169,19 @@ Function 492: UpdateMeshBuffer() (5 input parameters) Param[3]: data (type: const void *) Param[4]: dataSize (type: int) Param[5]: offset (type: int) -Function 493: UnloadMesh() (1 input parameters) +Function 494: UnloadMesh() (1 input parameters) Name: UnloadMesh Return type: void Description: Unload mesh data from CPU and GPU Param[1]: mesh (type: Mesh) -Function 494: DrawMesh() (3 input parameters) +Function 495: 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 495: DrawMeshInstanced() (4 input parameters) +Function 496: DrawMeshInstanced() (4 input parameters) Name: DrawMeshInstanced Return type: void Description: Draw multiple mesh instances with material and different transforms @@ -4183,35 +4189,35 @@ Function 495: DrawMeshInstanced() (4 input parameters) Param[2]: material (type: Material) Param[3]: transforms (type: const Matrix *) Param[4]: instances (type: int) -Function 496: GetMeshBoundingBox() (1 input parameters) +Function 497: GetMeshBoundingBox() (1 input parameters) Name: GetMeshBoundingBox Return type: BoundingBox Description: Compute mesh bounding box limits Param[1]: mesh (type: Mesh) -Function 497: GenMeshTangents() (1 input parameters) +Function 498: GenMeshTangents() (1 input parameters) Name: GenMeshTangents Return type: void Description: Compute mesh tangents Param[1]: mesh (type: Mesh *) -Function 498: ExportMesh() (2 input parameters) +Function 499: 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 499: ExportMeshAsCode() (2 input parameters) +Function 500: 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 500: GenMeshPoly() (2 input parameters) +Function 501: GenMeshPoly() (2 input parameters) Name: GenMeshPoly Return type: Mesh Description: Generate polygonal mesh Param[1]: sides (type: int) Param[2]: radius (type: float) -Function 501: GenMeshPlane() (4 input parameters) +Function 502: GenMeshPlane() (4 input parameters) Name: GenMeshPlane Return type: Mesh Description: Generate plane mesh (with subdivisions) @@ -4219,42 +4225,42 @@ Function 501: GenMeshPlane() (4 input parameters) Param[2]: length (type: float) Param[3]: resX (type: int) Param[4]: resZ (type: int) -Function 502: GenMeshCube() (3 input parameters) +Function 503: 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 503: GenMeshSphere() (3 input parameters) +Function 504: 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 504: GenMeshHemiSphere() (3 input parameters) +Function 505: 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 505: GenMeshCylinder() (3 input parameters) +Function 506: 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 506: GenMeshCone() (3 input parameters) +Function 507: 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 507: GenMeshTorus() (4 input parameters) +Function 508: GenMeshTorus() (4 input parameters) Name: GenMeshTorus Return type: Mesh Description: Generate torus mesh @@ -4262,7 +4268,7 @@ Function 507: GenMeshTorus() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 508: GenMeshKnot() (4 input parameters) +Function 509: GenMeshKnot() (4 input parameters) Name: GenMeshKnot Return type: Mesh Description: Generate trefoil knot mesh @@ -4270,91 +4276,91 @@ Function 508: GenMeshKnot() (4 input parameters) Param[2]: size (type: float) Param[3]: radSeg (type: int) Param[4]: sides (type: int) -Function 509: GenMeshHeightmap() (2 input parameters) +Function 510: 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 510: GenMeshCubicmap() (2 input parameters) +Function 511: 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 511: LoadMaterials() (2 input parameters) +Function 512: 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 512: LoadMaterialDefault() (0 input parameters) +Function 513: LoadMaterialDefault() (0 input parameters) Name: LoadMaterialDefault Return type: Material Description: Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) No input parameters -Function 513: IsMaterialValid() (1 input parameters) +Function 514: 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 514: UnloadMaterial() (1 input parameters) +Function 515: UnloadMaterial() (1 input parameters) Name: UnloadMaterial Return type: void Description: Unload material from GPU memory (VRAM) Param[1]: material (type: Material) -Function 515: SetMaterialTexture() (3 input parameters) +Function 516: 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 516: SetModelMeshMaterial() (3 input parameters) +Function 517: 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 517: LoadModelAnimations() (2 input parameters) +Function 518: 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 518: UpdateModelAnimation() (3 input parameters) +Function 519: UpdateModelAnimation() (3 input parameters) Name: UpdateModelAnimation Return type: void Description: Update model animation pose (CPU) Param[1]: model (type: Model) Param[2]: anim (type: ModelAnimation) Param[3]: frame (type: int) -Function 519: UpdateModelAnimationBones() (3 input parameters) +Function 520: UpdateModelAnimationBones() (3 input parameters) Name: UpdateModelAnimationBones 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 520: UnloadModelAnimation() (1 input parameters) +Function 521: UnloadModelAnimation() (1 input parameters) Name: UnloadModelAnimation Return type: void Description: Unload animation data Param[1]: anim (type: ModelAnimation) -Function 521: UnloadModelAnimations() (2 input parameters) +Function 522: 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 522: IsModelAnimationValid() (2 input parameters) +Function 523: 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 523: CheckCollisionSpheres() (4 input parameters) +Function 524: CheckCollisionSpheres() (4 input parameters) Name: CheckCollisionSpheres Return type: bool Description: Check collision between two spheres @@ -4362,40 +4368,40 @@ Function 523: CheckCollisionSpheres() (4 input parameters) Param[2]: radius1 (type: float) Param[3]: center2 (type: Vector3) Param[4]: radius2 (type: float) -Function 524: CheckCollisionBoxes() (2 input parameters) +Function 525: 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 525: CheckCollisionBoxSphere() (3 input parameters) +Function 526: 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 526: GetRayCollisionSphere() (3 input parameters) +Function 527: 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 527: GetRayCollisionBox() (2 input parameters) +Function 528: 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 528: GetRayCollisionMesh() (3 input parameters) +Function 529: 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 529: GetRayCollisionTriangle() (4 input parameters) +Function 530: GetRayCollisionTriangle() (4 input parameters) Name: GetRayCollisionTriangle Return type: RayCollision Description: Get collision info between ray and triangle @@ -4403,7 +4409,7 @@ Function 529: GetRayCollisionTriangle() (4 input parameters) Param[2]: p1 (type: Vector3) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) -Function 530: GetRayCollisionQuad() (5 input parameters) +Function 531: GetRayCollisionQuad() (5 input parameters) Name: GetRayCollisionQuad Return type: RayCollision Description: Get collision info between ray and quad @@ -4412,158 +4418,158 @@ Function 530: GetRayCollisionQuad() (5 input parameters) Param[3]: p2 (type: Vector3) Param[4]: p3 (type: Vector3) Param[5]: p4 (type: Vector3) -Function 531: InitAudioDevice() (0 input parameters) +Function 532: InitAudioDevice() (0 input parameters) Name: InitAudioDevice Return type: void Description: Initialize audio device and context No input parameters -Function 532: CloseAudioDevice() (0 input parameters) +Function 533: CloseAudioDevice() (0 input parameters) Name: CloseAudioDevice Return type: void Description: Close the audio device and context No input parameters -Function 533: IsAudioDeviceReady() (0 input parameters) +Function 534: IsAudioDeviceReady() (0 input parameters) Name: IsAudioDeviceReady Return type: bool Description: Check if audio device has been initialized successfully No input parameters -Function 534: SetMasterVolume() (1 input parameters) +Function 535: SetMasterVolume() (1 input parameters) Name: SetMasterVolume Return type: void Description: Set master volume (listener) Param[1]: volume (type: float) -Function 535: GetMasterVolume() (0 input parameters) +Function 536: GetMasterVolume() (0 input parameters) Name: GetMasterVolume Return type: float Description: Get master volume (listener) No input parameters -Function 536: LoadWave() (1 input parameters) +Function 537: LoadWave() (1 input parameters) Name: LoadWave Return type: Wave Description: Load wave data from file Param[1]: fileName (type: const char *) -Function 537: LoadWaveFromMemory() (3 input parameters) +Function 538: 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 538: IsWaveValid() (1 input parameters) +Function 539: 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 539: LoadSound() (1 input parameters) +Function 540: LoadSound() (1 input parameters) Name: LoadSound Return type: Sound Description: Load sound from file Param[1]: fileName (type: const char *) -Function 540: LoadSoundFromWave() (1 input parameters) +Function 541: LoadSoundFromWave() (1 input parameters) Name: LoadSoundFromWave Return type: Sound Description: Load sound from wave data Param[1]: wave (type: Wave) -Function 541: LoadSoundAlias() (1 input parameters) +Function 542: 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 542: IsSoundValid() (1 input parameters) +Function 543: 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 543: UpdateSound() (3 input parameters) +Function 544: UpdateSound() (3 input parameters) Name: UpdateSound Return type: void Description: Update sound buffer with new data (data and frame count should fit in sound) Param[1]: sound (type: Sound) Param[2]: data (type: const void *) Param[3]: sampleCount (type: int) -Function 544: UnloadWave() (1 input parameters) +Function 545: UnloadWave() (1 input parameters) Name: UnloadWave Return type: void Description: Unload wave data Param[1]: wave (type: Wave) -Function 545: UnloadSound() (1 input parameters) +Function 546: UnloadSound() (1 input parameters) Name: UnloadSound Return type: void Description: Unload sound Param[1]: sound (type: Sound) -Function 546: UnloadSoundAlias() (1 input parameters) +Function 547: 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 547: ExportWave() (2 input parameters) +Function 548: 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 548: ExportWaveAsCode() (2 input parameters) +Function 549: 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 549: PlaySound() (1 input parameters) +Function 550: PlaySound() (1 input parameters) Name: PlaySound Return type: void Description: Play a sound Param[1]: sound (type: Sound) -Function 550: StopSound() (1 input parameters) +Function 551: StopSound() (1 input parameters) Name: StopSound Return type: void Description: Stop playing a sound Param[1]: sound (type: Sound) -Function 551: PauseSound() (1 input parameters) +Function 552: PauseSound() (1 input parameters) Name: PauseSound Return type: void Description: Pause a sound Param[1]: sound (type: Sound) -Function 552: ResumeSound() (1 input parameters) +Function 553: ResumeSound() (1 input parameters) Name: ResumeSound Return type: void Description: Resume a paused sound Param[1]: sound (type: Sound) -Function 553: IsSoundPlaying() (1 input parameters) +Function 554: IsSoundPlaying() (1 input parameters) Name: IsSoundPlaying Return type: bool Description: Check if a sound is currently playing Param[1]: sound (type: Sound) -Function 554: SetSoundVolume() (2 input parameters) +Function 555: 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 555: SetSoundPitch() (2 input parameters) +Function 556: 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 556: SetSoundPan() (2 input parameters) +Function 557: 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 557: WaveCopy() (1 input parameters) +Function 558: WaveCopy() (1 input parameters) Name: WaveCopy Return type: Wave Description: Copy a wave to a new wave Param[1]: wave (type: Wave) -Function 558: WaveCrop() (3 input parameters) +Function 559: 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 559: WaveFormat() (4 input parameters) +Function 560: WaveFormat() (4 input parameters) Name: WaveFormat Return type: void Description: Convert wave data to desired format @@ -4571,203 +4577,203 @@ Function 559: WaveFormat() (4 input parameters) Param[2]: sampleRate (type: int) Param[3]: sampleSize (type: int) Param[4]: channels (type: int) -Function 560: LoadWaveSamples() (1 input parameters) +Function 561: 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 561: UnloadWaveSamples() (1 input parameters) +Function 562: UnloadWaveSamples() (1 input parameters) Name: UnloadWaveSamples Return type: void Description: Unload samples data loaded with LoadWaveSamples() Param[1]: samples (type: float *) -Function 562: LoadMusicStream() (1 input parameters) +Function 563: LoadMusicStream() (1 input parameters) Name: LoadMusicStream Return type: Music Description: Load music stream from file Param[1]: fileName (type: const char *) -Function 563: LoadMusicStreamFromMemory() (3 input parameters) +Function 564: 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 564: IsMusicValid() (1 input parameters) +Function 565: 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 565: UnloadMusicStream() (1 input parameters) +Function 566: UnloadMusicStream() (1 input parameters) Name: UnloadMusicStream Return type: void Description: Unload music stream Param[1]: music (type: Music) -Function 566: PlayMusicStream() (1 input parameters) +Function 567: PlayMusicStream() (1 input parameters) Name: PlayMusicStream Return type: void Description: Start music playing Param[1]: music (type: Music) -Function 567: IsMusicStreamPlaying() (1 input parameters) +Function 568: IsMusicStreamPlaying() (1 input parameters) Name: IsMusicStreamPlaying Return type: bool Description: Check if music is playing Param[1]: music (type: Music) -Function 568: UpdateMusicStream() (1 input parameters) +Function 569: UpdateMusicStream() (1 input parameters) Name: UpdateMusicStream Return type: void Description: Updates buffers for music streaming Param[1]: music (type: Music) -Function 569: StopMusicStream() (1 input parameters) +Function 570: StopMusicStream() (1 input parameters) Name: StopMusicStream Return type: void Description: Stop music playing Param[1]: music (type: Music) -Function 570: PauseMusicStream() (1 input parameters) +Function 571: PauseMusicStream() (1 input parameters) Name: PauseMusicStream Return type: void Description: Pause music playing Param[1]: music (type: Music) -Function 571: ResumeMusicStream() (1 input parameters) +Function 572: ResumeMusicStream() (1 input parameters) Name: ResumeMusicStream Return type: void Description: Resume playing paused music Param[1]: music (type: Music) -Function 572: SeekMusicStream() (2 input parameters) +Function 573: 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 573: SetMusicVolume() (2 input parameters) +Function 574: 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 574: SetMusicPitch() (2 input parameters) +Function 575: 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 575: SetMusicPan() (2 input parameters) +Function 576: 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 576: GetMusicTimeLength() (1 input parameters) +Function 577: GetMusicTimeLength() (1 input parameters) Name: GetMusicTimeLength Return type: float Description: Get music time length (in seconds) Param[1]: music (type: Music) -Function 577: GetMusicTimePlayed() (1 input parameters) +Function 578: GetMusicTimePlayed() (1 input parameters) Name: GetMusicTimePlayed Return type: float Description: Get current music time played (in seconds) Param[1]: music (type: Music) -Function 578: LoadAudioStream() (3 input parameters) +Function 579: 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 579: IsAudioStreamValid() (1 input parameters) +Function 580: 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 580: UnloadAudioStream() (1 input parameters) +Function 581: UnloadAudioStream() (1 input parameters) Name: UnloadAudioStream Return type: void Description: Unload audio stream and free memory Param[1]: stream (type: AudioStream) -Function 581: UpdateAudioStream() (3 input parameters) +Function 582: 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 582: IsAudioStreamProcessed() (1 input parameters) +Function 583: IsAudioStreamProcessed() (1 input parameters) Name: IsAudioStreamProcessed Return type: bool Description: Check if any audio stream buffers requires refill Param[1]: stream (type: AudioStream) -Function 583: PlayAudioStream() (1 input parameters) +Function 584: PlayAudioStream() (1 input parameters) Name: PlayAudioStream Return type: void Description: Play audio stream Param[1]: stream (type: AudioStream) -Function 584: PauseAudioStream() (1 input parameters) +Function 585: PauseAudioStream() (1 input parameters) Name: PauseAudioStream Return type: void Description: Pause audio stream Param[1]: stream (type: AudioStream) -Function 585: ResumeAudioStream() (1 input parameters) +Function 586: ResumeAudioStream() (1 input parameters) Name: ResumeAudioStream Return type: void Description: Resume audio stream Param[1]: stream (type: AudioStream) -Function 586: IsAudioStreamPlaying() (1 input parameters) +Function 587: IsAudioStreamPlaying() (1 input parameters) Name: IsAudioStreamPlaying Return type: bool Description: Check if audio stream is playing Param[1]: stream (type: AudioStream) -Function 587: StopAudioStream() (1 input parameters) +Function 588: StopAudioStream() (1 input parameters) Name: StopAudioStream Return type: void Description: Stop audio stream Param[1]: stream (type: AudioStream) -Function 588: SetAudioStreamVolume() (2 input parameters) +Function 589: 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 589: SetAudioStreamPitch() (2 input parameters) +Function 590: 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 590: SetAudioStreamPan() (2 input parameters) +Function 591: 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 591: SetAudioStreamBufferSizeDefault() (1 input parameters) +Function 592: SetAudioStreamBufferSizeDefault() (1 input parameters) Name: SetAudioStreamBufferSizeDefault Return type: void Description: Default size for new audio streams Param[1]: size (type: int) -Function 592: SetAudioStreamCallback() (2 input parameters) +Function 593: 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 593: AttachAudioStreamProcessor() (2 input parameters) +Function 594: AttachAudioStreamProcessor() (2 input parameters) Name: AttachAudioStreamProcessor Return type: void Description: Attach audio stream processor to stream, receives frames x 2 samples as 'float' (stereo) Param[1]: stream (type: AudioStream) Param[2]: processor (type: AudioCallback) -Function 594: DetachAudioStreamProcessor() (2 input parameters) +Function 595: 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 595: AttachAudioMixedProcessor() (1 input parameters) +Function 596: AttachAudioMixedProcessor() (1 input parameters) Name: AttachAudioMixedProcessor Return type: void Description: Attach audio stream processor to the entire audio pipeline, receives frames x 2 samples as 'float' (stereo) Param[1]: processor (type: AudioCallback) -Function 596: DetachAudioMixedProcessor() (1 input parameters) +Function 597: DetachAudioMixedProcessor() (1 input parameters) Name: DetachAudioMixedProcessor Return type: void Description: Detach audio stream processor from the entire audio pipeline diff --git a/tools/rlparser/output/raylib_api.xml b/tools/rlparser/output/raylib_api.xml index 59f2d4a50..96dbdbf64 100644 --- a/tools/rlparser/output/raylib_api.xml +++ b/tools/rlparser/output/raylib_api.xml @@ -679,7 +679,7 @@ - + @@ -1168,6 +1168,10 @@ + + + + diff --git a/tools/rlparser/rlparser b/tools/rlparser/rlparser new file mode 100755 index 0000000000000000000000000000000000000000..b68032c023debdd4b5e656b794864b81bd2e123c GIT binary patch literal 43144 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 Date: Wed, 15 Oct 2025 19:37:17 +0200 Subject: [PATCH 022/102] Added clock of clocks example (#5263) --- examples/shapes/shapes_clock_of_clocks.c | 227 +++++++++++++++++++++ examples/shapes/shapes_clock_of_clocks.png | Bin 0 -> 23916 bytes 2 files changed, 227 insertions(+) create mode 100644 examples/shapes/shapes_clock_of_clocks.c create mode 100644 examples/shapes/shapes_clock_of_clocks.png diff --git a/examples/shapes/shapes_clock_of_clocks.c b/examples/shapes/shapes_clock_of_clocks.c new file mode 100644 index 000000000..0418255e4 --- /dev/null +++ b/examples/shapes/shapes_clock_of_clocks.c @@ -0,0 +1,227 @@ +/******************************************************************************************* +* +* raylib [shapes] example - clock of clocks +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.5 +* +* Example contributed by JP Mortiboys (@themushroompirates) 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) 2025 JP Mortiboys (@themushroompirates) +* +********************************************************************************************/ + +#include "raylib.h" + +#include "raymath.h" // Required for: Lerp() +#include // Required for: time(), localtime() + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - clock of clocks"); + + const Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.75f); + const Color handsColor = ColorLerp(YELLOW, RAYWHITE, .25f); + + const float clockFaceSize = 24; + const float clockFaceSpacing = 8.0f; + const float sectionSpacing = 16.0f; + + const Vector2 TL = (Vector2){ 0.0f, 90.0f }; // Top-left corner + const Vector2 TR = (Vector2){ 90.0f, 180.0f }; // Top-right corner + const Vector2 BR = (Vector2){ 180.0f, 270.0f }; // Bottom-right corner + const Vector2 BL = (Vector2){ 0.0f, 270.0f }; // Bottom-left corner + const Vector2 HH = (Vector2){ 0.0f, 180.0f }; // Horizontal line + const Vector2 VV = (Vector2){ 90.0f, 270.0f }; // Vertical line + const Vector2 ZZ = (Vector2){ 135.0f, 135.0f }; // Not relevant + + const Vector2 digitAngles[10][24] = { + /* 0 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,VV,VV,VV,/* */ VV,VV,VV,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR }, + /* 1 */ { TL,HH,TR,ZZ, /* */ BL,TR,VV,ZZ,/* */ ZZ,VV,VV,ZZ,/* */ ZZ,VV,VV,ZZ,/* */ TL,BR,BL,TR,/* */ BL,HH,HH,BR }, + /* 2 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ BL,HH,HH,BR }, + /* 3 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR }, + /* 4 */ { TL,TR,TL,TR, /* */ VV,VV,VV,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,BL,BR }, + /* 5 */ { TL,HH,HH,TR, /* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR }, + /* 6 */ { TL,HH,HH,TR, /* */ VV,TL,HH,BR,/* */ VV,BL,HH,TR,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR }, + /* 7 */ { TL,HH,HH,TR, /* */ BL,HH,TR,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,VV,VV,/* */ ZZ,ZZ,BL,BR }, + /* 8 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,HH,BR }, + /* 9 */ { TL,HH,HH,TR, /* */ VV,TL,TR,VV,/* */ VV,BL,BR,VV,/* */ BL,HH,TR,VV,/* */ TL,HH,BR,VV,/* */ BL,HH,HH,BR }, + }; + // Time for the hands to move to the new position (in seconds); this must be <1s + const float handsMoveDuration = .5f; + + // We store the previous seconds value so we can see if the time has changed + int prevSeconds = -1; + + // This represents the real position where the hands are right now + Vector2 currentAngles[6][24] = { 0 }; + + // This is the position where the hands were moving from + Vector2 srcAngles[6][24] = { 0 }; + // This is the position where the hands are moving to + Vector2 dstAngles[6][24] = { 0 }; + + // Current animation timer + float handsMoveTimer = 0.0f; + + // 12 or 24 hour mode + int hourMode = 24; + + 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 + //---------------------------------------------------------------------------------- + + // Get the current time + time_t rawtime; + struct tm *timeinfo; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + if (timeinfo->tm_sec != prevSeconds) { + // The time has changed, so we need to move the hands to the new positions + prevSeconds = timeinfo->tm_sec; + + // Format the current time so we can access the individual digits + const char *clockDigits = TextFormat("%02d%02d%02d", timeinfo->tm_hour % hourMode, timeinfo->tm_min, timeinfo->tm_sec); + + // Fetch where we want all the hands to be + for (int digit = 0; digit < 6; digit++) { + for (int cell = 0; cell < 24; cell++) { + srcAngles[digit][cell] = currentAngles[digit][cell]; + dstAngles[digit][cell] = digitAngles[ clockDigits[digit] - '0' ][cell]; + + // Quick exception for 12h mode + if (digit == 0 && hourMode == 12 && clockDigits[0] == '0') { + dstAngles[digit][cell] = ZZ; + } + + if (srcAngles[digit][cell].x > dstAngles[digit][cell].x) { + srcAngles[digit][cell].x -= 360.0f; + } + if (srcAngles[digit][cell].y > dstAngles[digit][cell].y) { + srcAngles[digit][cell].y -= 360.0f; + } + } + } + + // Reset the timer + handsMoveTimer = -GetFrameTime(); + } + + // Now let's animate all the hands if we need to + if (handsMoveTimer < handsMoveDuration) { + // Increase the timer but don't go above the maximum + handsMoveTimer = Clamp(handsMoveTimer + GetFrameTime(), 0, handsMoveDuration); + + // Calculate the % completion of the animation + float t = handsMoveTimer / handsMoveDuration; + + // A little cheeky smoothstep + t = t * t * (3.0f - 2.0f * t); + + for (int digit = 0; digit < 6; digit++) { + for (int cell = 0; cell < 24; cell++) { + currentAngles[digit][cell].x = Lerp(srcAngles[digit][cell].x, dstAngles[digit][cell].x, t); + currentAngles[digit][cell].y = Lerp(srcAngles[digit][cell].y, dstAngles[digit][cell].y, t); + } + } + + if (handsMoveTimer == handsMoveDuration) { + // The animation has now finished + } + } + + // Handle input + + // Toggle between 12 and 24 hour mode with space + if (IsKeyPressed(KEY_SPACE)) { + hourMode = 36 - hourMode; + } + + + + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(bgColor); + + DrawText(TextFormat("%d-h mode, space to change", hourMode), 10, 30, 20, RAYWHITE); + + float xOffset = 4.0f; + + for (int digit = 0; digit < 6; digit++) { + + for (int row = 0; row < 6; row++) { + for (int col = 0; col < 4; col++) { + Vector2 centre = (Vector2){ + xOffset + col*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f, + 100 + row*(clockFaceSize+clockFaceSpacing) + clockFaceSize * .5f + }; + DrawRing(centre, clockFaceSize * 0.5f - 2.0f, clockFaceSize * 0.5f, 0, 360, 24, DARKGRAY); + + // Big hand + DrawRectanglePro( + (Rectangle){centre.x, centre.y, clockFaceSize*.5f+4.0f, 4.0f}, + (Vector2){ 2.0f, 2.0f }, + currentAngles[digit][row*4+col].x, + handsColor + ); + + // Little hand + DrawRectanglePro( + (Rectangle){centre.x, centre.y, clockFaceSize*.5f+2.0f, 4.0f}, + (Vector2){ 2.0f, 2.0f }, + currentAngles[digit][row*4+col].y, + handsColor + ); + } + } + + xOffset += (clockFaceSize+clockFaceSpacing) * 4; + if (digit % 2 == 1) { + + DrawRing((Vector2){xOffset + 4.0f, 160.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); + DrawRing((Vector2){xOffset + 4.0f, 225.0f}, 6.0f, 8.0f, 0.0f, 360.0f, 24, handsColor); + + xOffset += sectionSpacing; + + } + } + + DrawFPS(10, 10); + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_clock_of_clocks.png b/examples/shapes/shapes_clock_of_clocks.png new file mode 100644 index 0000000000000000000000000000000000000000..fb91d7263d90be64df868cbbc616fa7eb707c4ef GIT binary patch literal 23916 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úJpOh773uNG9{4zV`mI6)PGnX(tZDm(y2x2?Si_%_{Z{y8Ej5aysB2pDaU51 zso0h~d*6bLt)*=erH`Iz&$5zBvp*q}r&qQic0o6Xef?j?w9BXe1^(}U^Fw~+%l=De zY@_NNPMx0^SI1lO(=zM-fhqSFKV?q^74(w1^-Z_#A71)TVHfkGEEV?sl`@lB1Go)t znEqs3^oK`3u0CZ!nLESfIu|##QkR6eg1>Iszp8(-sN~7f|0lfar1PrvCOtafm)&GQxY+%eyAGjIRAy~#U@ z+IUrE5{wl#v}t%ul9CmS`PO`9|4*i%&W0--pNbprI_v*-|7*YLas84d;KtZfc7En< zNH)y}+mz#aBI7rE^-s%7x8n~l{deFt5?;oibpNg;4-I@*x9n>aOL74-G zsnSQ$2Me0mBmaZyjRaZoByLqN>5W^q)nEC)LwmzSf&VR+J_h*LU&*maSl!}Y^-uEM z%k&M`<(cRHYuo*I@l*CiA1!YETUhryf6KoE^AERq{bqiy8L?p|e^K>^1-1$bdlw`) z#WgwP95l(Yx3^f~c6k0C!6_HNeD7+U^v69DT!21{50H}5-S3w6(=@6sAnacsxaH`f zVZX7=!C|kumkqymjYF@)g-f~u@>@E)Za8ILsWWW5_#u744})f~QFH#dXFg5@w`wnb z%6>8}e(_Uw6&APG@}FMKzxXTp$rbqsYlRK>%uW3^G37?Er@F^j|JW!Rw)mTK)&Ip0 z{eMn8xA-OhCiC_wSe>Ncl(6NW;@*FfYwg|q{x)7@bbME96u{Wf8!vwO-r5KAODtB5Q`1$wm@qCr1)n9@+4NUj9ayfDZK1q(A zcvbG+Z}t3;QoFcIxGn3C@V7r1 zzmgX)gX;CC;u_QMLS&Z>VnwwGUEp0VvK|I)AWhwPtBjaSzF z-*?QuG)X3zjb&TdoGZ!2l5B^!<`AdiXA2#eTNrpN3KYd2=|;E`5HV@teK;=g}huTx}s7 z3(D=>7U!dl#X`AlK^zGs4li~lPK{$^z5R#pv$S1x=EM4|oBgXlZ!EvhzsGw6+pYh~ zdp#t)UiM$wA=UTvxWn@M4}$o3a zBXdgMi|bzCfBwI}vK6Egzj)aHIAt7l#s12={|WEd?_PKF`Q0t@+uiA(Y;XM?O{Vxi z$!8jR=1Ca-@atKyFGsYBPEES_DS68u z30-@(=bfQjBwP->Xi&(PP0gt4`LZ9>fce+@O;% zVk#&rf;%A@f4RMQm&Ba0n)J$ljqHTG&*d761u}FMbeJawuQ+hcPU!aU=9`9D|CQVR z+LXVcW%T z>>oGVD{uVU`dK3Gf?7d9LxYfjWvfQfGv%e<*}GdN=GbT46g9P$U;Oa@#3xpTOP1Gr zNeeE1dc3&p;-|@tiCg|XNSEmR`aI)jV@6H?wf&2~>aYBnxa7)w3;%;mYgvV#{O4Hb za9}Ej0ZV6OGuN%{3{h1KyG=T0OkTgi^_<7n{d*^fzTULDxqU{*uD3NNe<~&1F3%TW z-uaV%%D+QSmIot){P==wY^uJrKm0b=UghpKdz3cVq*v!bvG`ANZT-ph^@+I;CkE9U z8Fgg*KYrcXdEQBemCawD-LL<1jN$eMrrT@!=6rC-;*?$L?XzBB`rr2N{~Rx_Oa9cI zxZ_6uzK?%S1nRYQPFCzabWrFYv+V!HFZ+MJoIk@`&oh#V}NEmXwrI z+B1*0Ee$-9zWX~=B^P{Yq&J)9)Ui?f0JUpE$4H?e+bKcmFAe)bULJp}vc` z>5d@d#>$kHp$~_p*~#QvVMt|C{M1%>iyy zDVwu6ES|1#zd6mM;B1XTJD&${MyHqu&$h@~lfU3;o}M!T61w(o!T&%_EQXzm2aH0R z`|c^by?AJH;ak7j&qm(Hhm-z=getfm`1yH%CttvYe*!mx)?6&{h~wz_@+teu|MzSr zuLHFIu&;tT!5Zv@_BTRnF1DQqoBC9dVfHDttq$tp_cP{zCo6d7Lu>`l%P{POOai}! zI0&hE2b;RMpvwZ9lkLnkVR0+qIPk5w!ECy)G>^engT0G6Gr*;9O51^qpN6wOfoBCz zKvoFck_64UBq*dhTfXoU2$;~A=Pu8?3p6qZT1B9151kufSgCm6%mLMF22zk|Z)IZ^ zm7o6%BO*5%fB0-{Sn&7%;SJx9*zaLvob|V(^BLRf!0mrcX63kn*EbY!fExBE>p_la zxFewOQ$z>SlsqB%>`u&^glb1|!McCHn9tZ1eirpjW={LR%{M;a&BoF+$-r;THr5j! z+FyDrulJI_WX-yT5Bb^B)%n;?oD4e>@8aR-Ca(joAtuJv_5P}_xDwACTGw;!KM#-c z&VTZ~{~rqecPV#>>3#BmQ*Q4=##0;{&Il-+I{)F(S9i9oauwhe<@86NnV=ZQQz*=zuALomRxEp&F7DV!25aPD9^eA*Zr~9IL{U3=J zU#u^kULW{h`TAn#o&Tg}d`jN(uYKwKiIM;NkNq#`sBb#{p~+3hG*snbsw!xd&iI7n zGxK-{Ax00-C|v~a8U@zE6&D2$rv9I5oO9x-IdcwM%90!WpZ++sft+En%>KgCqy;kt z*lZfEoI9SNYtLr&w-2124zK^WC>>P$8XNRH`BiW7uigF6#Od2(?FNTuJmtS7IT)gT*Dtwkf9JA1b8Ete>GI5T>)fk;n!c*P!#m?) zK>fvCe0@a8*3j^!sfn|aQ+y-qIlDL)!{#M-k|Kf+`e>|RF{K9T& z&@|!^ctdesUuh!g6-h(ysG_+ANp5v^eo%2&$Hx-eO6yw-?IA`zj$YI^gN5d^y$6B_4$jRvcre+ zZqNUcTW=H?l+fU}n<3FD?SLC&g1Cgy1xcRp-|mO!?`ScZ^-p1O0Q1!U8fV`v{%F48 zqq)?-#Si&U9bWvDy;AjN#y`ok_RKTu*@}N1-qA5(`fTPor@=#c+ZE^k^wTD8@AdY0 z=={mEQrsTbC)~1U7X2?_tgvD0qaS@|UH2DolvGOYn<+3O^2i!z^<#BG!e0wE*RN=` zKg_}Itob)kDs;<<{fl3+7d?EP@$;mgfhN!KFXo_*2oq1qkKSqV%Dewa_153{=>JJb zCn?W5Rf5%oyYb=&dEXdtF^@(#Te28fDf}>7^C;`jySv|;8Se|}+;~h9x>^( z_U^yVrhnY41P!NLl3!ZrdY<>avTAJawD~p-aRmAv5c&5WOpkvt%)uhlcpu6KW2 zpAf9D??bxcwah1Gb&k)tKNUBw{rTtX@rITo1sm!&wA=49U9cfKvUBH@GpGC88MpK_ z&AI)#P*pGKP5Vyyl6c;&Z{=UUoIk_IepX#U`=yMZo_~KePcePH`04Qj*X~a-lggM_ zzhZ7(LY>TtU;QD!J#QX1mpQ%u;tz2ptLR7F^*xdTIo8iKGyhDAs_2;~(O8*uB;&{B z_4lnn4KhVg>pYrud%p0c7^Q9JNIN$tt z@x$^OkwTNdf!~u9lemst{PTNqW7Oh^#V@CS`C>imADh|Vz*`woz579JF3?yT=i7Kl zlhp9Z^Sbm68;|YbZn<)f-SYaa<~QwMn-WD0EL){=-s*Y0@0`89!z{_*hP~83o(Fps zluiG!8~qIi55Ms$XA&N^M(^|y5^GgH(z=d%xY!%87HuB(K!R+j(ppgD=VcP$UAD}Y#2m8|Bjo<8-_I6zSQGL!J==A!76Y9X7 ziTxKpIrlJ{{jj?A@8=1FTmO`GS=_vSwia@QRV!*=OATk|H#8I|zHOOtS1#ifN139C zp}Krxx73BG0LOp*4}5suwJ?YZ8h0CBc`MIb?~x_3@+1FgZsxc3UeW@KKYnjbRGAjv ztopZa+5SdfP>4Udbmro>^X_axVe@;Y$t$n^d-#OHqQCNcH#pq?QS(GY{P2;Ja}rWF z-23yp|Gq?m^s$85trM)}6pmi8@Di<5V@^>!^Y3u={{0_be5W(Tw6MMphJQGu4>;~G($#8k>@!-`)~Kd@}>`YwtX?bbjg0J zv=H;$dUmUSZl}*T>h5=cJb&Lqd&rd8Tm372Uo!qSTHEq2{ic78kK;u3f~O8s|Lza0 z;kw;_@buY(4AE(<)?1lM+Dvo8S{mIL((J4Fc}g137i_LK`C}-2F~PH5+4OJlVns%y z2C@w3y4+4=paYLkELYJc2M^PjR-QV@1K-GA{@vc;DDAIlsh*bE)^cTS!% zTXW^ZwT;{6CyMmE0FMJoHcSFF$RyoP^DhxtQ2y65^FjZ#dgj?R?jYUGja*OJg%4}s zUU13FXw`aP0%$N$5v?pjaGmubgL!X3Z9-Vf4!Oxkg~2>3j3+j(rTxFd@A@Te_Dg40Z+HSqOHp-v zDL*Zv>L!Fw0<{a@>IeKTUU0j9@mKcJSNw~t71p^GeVBdzVmDuaBcJveW|yCmaeMxq zaCqCtvFz^(Mg_(#;!oC1Otx1Nb4&ZdzvaJs*pJ{_A0=vjmYe)lIQ}x@=gD&p_kSgC z`J=GZM^e|`?RNYIGc}dFJSCu^uLW*@9Y4qkTtLb(Z;m_s{28Xwew@ zOm>dF&>Q)e5A84fljnTspZPr5;5j6S9(gf;Sz+&Xn*Y$!(-}VvZ~Z%T^`Fd(Z}&6) zI?nyYoX*~I$w>k-7TED}hl0D7;_r{D4ihX7->q{x`hCTJ!B%tKOZN-->$A%2Ht;&} zl>C!@@k9FM&vKK0AD1^QjH~OPCcpSA|C-MRGT@MZ$H$@hHh<3Ygo8r-JB=m4BZ3OY z75o*2q78a)o#*FUb@79GzWv3FU)4t)Ji(I_knsp!P|dp;)O^y=u6G9oMzPA2`4QF% z3oeSIjR^KoHX_)R8{uwykfC1CG|PU;cYCRSQ{-RT%=)KLz1ZVq{S-3=@L&k*(uEg4 zWv75g7L`CFiSsP*#PB^3+ z#DEIyM?#k}el_(bDZR^;^mciueAUQomL?ng7L-p-fo;Z-W8m)f#^T1x$Y-{$() zbEUf5Y5q^A{!fgn3s_yGZ1$IT+qdHZy`Z+kji|z!l_97Uv)f~&Dl89^^8?X z(i?TtjlAZd=4GPD1OcWcOX|Itr-}V6U*i7FL*L&0v3$|P_W>*H-B0%)oF3(VJDz!V zJ)4y)&$A!um7HQ#kIT2HdfXR~;QfD5#2j^E1hPDOiZjDv=BE6^TI-Izhs>=u<=VB+ z?A1Szu`#i12dMg9+{$aI=-~Bhxk<~*oeyi5ENPnxhopK&bxc!55rv8cZtlOS_zAn!!B!2kdzl$G^&oB9~wz1`|md}}` z8F6(sJPVfcJ-KtQ>vZdp8~nxgFZRh~-L}8*Qa*aegiUFs8b{>M^dDI!A9PKC|M;h3 zlYgxp>$u&kKr?*_Z3jH`?L9I*E-C-Nu=}rJ%p>_^HkR9cm0nW&mwdBu^Y1xeW0+*} z=jHW$SO7pw0B&%L%g@h~&8f#*x7v>wO+6@-0DJ_#>oZrYQ`YEtUldrV(b z{Pcp`{=H5$8n;2oe0jsgFYbH0dpV9C%lPM-Q=#(go^n#q_l#evcF=aflxf!%e>9J( zYq%tkA$lO==gGqccW&>GFkg81+NrZMG!8IWXNg-XaJ>EL5axaEsGh;^m4;nrQ$XqU zl)E5kR7hV;X_O5EXO)KW?lOI`sA_6b)Ef*#9H z6KA{iA5^$Je$Rc_LuWsm_b*xBdgj^x+)neC6$tcftG6?nu<2LImOm1aZ{@)gu`gO# ze;s=com*{5*ARI8_jo?f2HxZiXPr*S@=uV;l1c5dnapS;Y&NT);=Q~``s*2gk|gxL z^|#q8WwB@f;V=2MeCpo?d<792D(g?5bUdamXZ!1L!S8eOi`Wz{oED1tXdZL8KjJ_C z^H1ECJZ_KW4TbE4UV)al$j1!(10Oqk|qf{{@5V_@@72&Sqy3Vc6hikaM2B z%IU!Lc@DErU>z&0H~AANd@iB;f1}_3EgR&ocV?d`o4ARcC*ILY<}m;K`EF4^Tjj)> z*Zz}u@x@%`_42|xmUt$GkTlU|^&CE<(HWxD7Qvc_(eQ9IqIFF^B zwoRU8FFVIBhMXNY?WO+B=*-w~9g5QEs?X@#5v*GYxhx7(Q#QP!0+@!~HDi5@(_W zD-UQV-o`JxxDC=8JHf|zBi87|` zThTl%OEbDws<#b1*d{2&1X_!63A{~0!5rKSynHT$qvwG@KxpHflG1;F@)tQXZm~}> zxd?9%{xqD$1|DJq4dzKsxVXhwib>gmB_TW0GuGK_-9FgqBd-ls&4BsScw^YaO4c*nxHlKF0*om2_f(#47fQFT4b zKx2x$j6u!~ts%Uxglu?)r2|w=ImS>v=Z6QP;lR z`=6ruU;gQkq`?q-#OBt&M9JL$jLr#L{(49Kp8tZcWA#LtKhKK4IEh~oXftg?v@kmk zY?0r}G?n2NchU6|8|4ML7e73Iz~TQ7`4=CS_x)Y4+m?s7-k`xsbb>cq=l+ffQ;uDK zpl$E=nZM{y?=$(bwuzyjRv&28L&EL#{l*pb?p43@D}Ky>pc%11lHFI-vm%!D)mwW| zd$T=uH-C`wiSw*t&7mm@e5O`PJKpRsYU5q{msy%oUh`YCjlI;r4i$&@V7s^dJ+WP~ zInR<^_B8iyL0Oa6j8RF9vs4*xdY{sL0h%c|YtI~A$G82@;RfcODIlLqP?q&zI(T^6t0mcig^z zcr z8zyHqtLDJpii-snKh!^BAds+RxxLrn8k7Hg=l^iuTElawN(a!R!AHLPryC->*MXf7o**+U;5D^;3@mkhvt_~ z>sLLGf1(^+u9K9Y@I0(GCr{1nFYlJWJSI%cv7j!@4yS~Q?e%QC{>i_3+rRMMKUMQT zhG`B7*+)HX&88;`FwcnZh-9~aRez%Qz?Gi=6XpIf&o%YntoOQWCG+`wK$m?~i~ZKm z`oC%g7exQ~c(#Sd{I{pCKWHh*GHfxT^BemT(1sVY>Jv*GCYY}Y$d=^O6hGZ_>pyEuQ)8N=+u`}`TA|-Fel5Ot z)U8D+#pHh*T2;AGGwxPyAk!sU`q)pirEf=&H5F{&>3 zR)&l&sDm9KC6)W1=l?hUYkVi(757Ud>$qp=HmYwO1Qo1nREYp=z)qW500K~^+zO5oZY|p>;D5+ z|9@GtzfkTl_bnDaFBZ@eLuC%j&y8mDCr4@Y-ugc$(d3V$gxh6#`@>)h1Q-7-fATE; z!Y1{sGCPm8_H4K60`5t^d|AKckAulR_uKaJpf=Z%)&m}z_675rSfjetPW%_V!@y$B z)cDZ-j1F7IeWr|8JY@@c_Dx>@!S&>dzwr`op!MmEpYDMz0Qn&0*?p9DvDfSV#%=P` z^4+R_$?MuHi2v$?Hg8i+{yR7&ESVzT!=rTT|3^`=6ULGXr5o=3dAPSeV9U!Hf07*D zRWzuqES#dJ_ZvF@&3t=}?W8yIFFwfk{%`cH|H4)8B`vi0DSMKN$j(19FFtiod&yq= z`1{1gF+9TR#YPuS|7Xs%FPbO02INPDbt%%h^$Gg>-EPY-e(V24#wG9f`~-HEG|now zn7xm5z4-Wg1=>D4f*P_XBtVni$J5_fSF_r*u+8<+lP{B(@!G`scBK^J5XbM$}y>A#v^@Nt|uyy5GM z7q$r(SgRHouSwi2#ACu_@Vj!Sr9{H%JqgRxdQ`xZX^-m@F5h=(wKug=QZRPAeEx&K z{eq_fpz+B`JhrFbH*S-Uj+4{@O$Rx~d79n&*Dz<5#jSr5x%EoV6^d^ES1EUpa67nw zgYnDk3m@;YcyqJ!Z~3ciE7{lfKf}?*lcQ(Z{6=5<#ZSLy{F6NeD!1Lsek~3AW85o- zdokc*MThl}&36yPHyJBy#P zF9D^oY?J?eXZ~1U_?Zu070BlOJAKPv!wpZ5LspjVkUDu#I%a}S%Pq!<0#Dhw*%@An zLv~{{WZEk!H%m2bIQHNKXd zdcPf?-LGLh$)aG|^d~0adyfbtWzBC)RJbg^_YlOggNGZ|!o1T1^G=TIiGuW{smU2#Av_Q$#;cj#c_53X$!6aG82|IhgI*st-6NBtL$deEMR zr|j=O6)!lw{^B3&KcC-&*Az83Chh=jxsYd$uH%^w9%l?t=89)xVdVo)_8xZc?$n*4 zk$Z%<9O6*5VS z&fdq?dLKMy>GyB(mXCy5X%X*dOQ}aTnyqQxr2J-z7W$O$_rAs}h?R#o7#Nmjf*M!z zppB~z@F1c7-@a?{Usmrouu?d&*Pl&`;li@g8yY$l;Kc|kP5V|rrh`Ci+^ULX%uKd!~zqOTmK|$-pcpjSb@j{8jcS8 z44U8-aS!#LD|Y$8HhICiEuZWQ7g|XDXP*3z&HGRAtm|%<&!6zKKXS}|#mDz=SXO42 z=_Dn5==kk6HK}gJjsAC$Uf^Zw0gtn`{AKhkzHvK#@mqe67d_yC(<3t&8{b}SxcmK} z0asfM$AL$aX4G0N{%HS4$Og2P;=Mb>>?8I?&zVJ{7W8rKn<qCKj*e_;m=f!8~oh<7iu-H zeA};JFK&@xSO3>>>l_2A|3}zW4PWN3IBLI?Gt=a6&zdjJd5`5qysl{MXS-GR<;Joy zP^DY&eEG$1>`%gqYTmBD_>EoVZ_hUSrxGu2{yQ>*QPS2h>B|w0fG`3%t7**dlO&;98aeo~jkfrc6>Dt7Q`lPoFZ|uHzFka(sO;sr361{QD z8#bW0;xBk7o5X=^Lv|(jRw{GUO&@>TmqrKtlFs<;UIbdD>;T&M!+f*a=+?hv&@fR_ z{(ocRf=<%}ZG(URe;rlOI&%5|^PU+24U=0Rp1i$YWvcdxnfzCND~JAv+Qz2$Kk!zE z#M%AI=Kq_f*;?NCf84|A39Lyr;kY}vsU*<*9yAHtcJZ5h=G*5JgX$iwtdA{e%7tpH5g&G`gr_W#f#-AhksvzgT;G2d6Mf_E62d1xv zuQhag>wdOl@xy*=7Prgy{n@gf+h>`pxLtn#!EgTtKZcx}qI<#3Alowcs=uaDbp`=j zm5rk6`mX)o;gq1UwZ7wB!vP!a+ajmA??^Mve%tW&7W>>p-r1sw3j`&$$``FVlJTS1 zpl6wVS%Kc-^nZ)poS9ONW&D!;_fmX|%&JZQ&AlcqO#f+n;al=)ZRNe7T~`|1jTgV2 z&-k5gadkeVd4*g)fC~czF+q~aXR#vIX$k05#TPE{ks(nyj|@qWc-zpUhSDuW8Bj|U zhnyu-1seauc34US!LwvQ+e7$HWZ*uw1mpzBxEgqH4V`!hal*<`Cm1U%9t{Q1(MF@8 zFd7Ptqve8t1n+1lfQKzd)52(4fVEpj)52(47)=YHJu#!9Fd7P@y(w@50gV`~BS!0p r(b93WbQ~=m(F#T|ces>}j11vTXSUy3QPju4z`)??>gTe~DWM4f$YiLJ literal 0 HcmV?d00001 From 2a04317cff9dfdd7e0880dc5105ced8ca48b1eb9 Mon Sep 17 00:00:00 2001 From: JordSant <77529699+JordSant@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:39:47 +0200 Subject: [PATCH 023/102] [examples] Added: `shapes_particles` (#5260) * [Examples] Added shapes_particles * Changes to follow the code conventions. Improved some things. * Fixed name * Fixed PNG name --------- Co-authored-by: Ray --- examples/shapes/shapes_simple_particles.c | 277 +++++++++ examples/shapes/shapes_simple_particles.png | Bin 0 -> 32265 bytes .../examples/shapes_simple_particles.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 8 + 4 files changed, 854 insertions(+) create mode 100644 examples/shapes/shapes_simple_particles.c create mode 100644 examples/shapes/shapes_simple_particles.png create mode 100644 projects/VS2022/examples/shapes_simple_particles.vcxproj diff --git a/examples/shapes/shapes_simple_particles.c b/examples/shapes/shapes_simple_particles.c new file mode 100644 index 000000000..aae85f35d --- /dev/null +++ b/examples/shapes/shapes_simple_particles.c @@ -0,0 +1,277 @@ +/******************************************************************************************* +* +* raylib [shapes] example - simple particles +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.6, last time updated with raylib 5.6 +* +* Example contributed by Jordi Santonja (@JordSant) +* +* 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) 2025 Jordi Santonja (@JordSant) +* +********************************************************************************************/ + +#include "raylib.h" + +#include // Required for: calloc(), free() +#include // Required for: cosf(), sinf() + +#define MAX_PARTICLES 3000 // Max number particles + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum ParticleType { + WATER = 0, + SMOKE, + FIRE +} ParticleType; + +static const char particleTypesChar[3][10] = { "WATER", "SMOKE", "FIRE" }; + +typedef struct Particle { + Vector2 position; // Particle position on screen + Vector2 velocity; // Particle current speed and direction + bool alive; // Particle alive: inside screen and life time + float lifeTime; // Particle life time + ParticleType type; // Particle type (WATER, SMOKE, FIRE) + float radius; // Particle radius + Color color; // Particle color +} Particle; + +typedef struct CircularBuffer { + int head; // Index for the next write + int tail; // Index for the next read + Particle *buffer; // Particle buffer array +} CircularBuffer; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition, ParticleType type); +static Particle *AddToCircularBuffer(CircularBuffer *circularBuffer); +static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight); +static void UpdateCircularBuffer(CircularBuffer *circularBuffer); +static void DrawParticles(CircularBuffer *circularBuffer); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - particles"); + + // Definition of particles + Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array + CircularBuffer circularBuffer = { 0, 0, particles }; + + // Particle emitter parameters + int emissionRate = -2; // Negative: on average every -X frames. Positive: particles per frame + ParticleType currentType = WATER; + Vector2 emitterPosition = { screenWidth/2.0f, screenHeight/2.0f }; + + 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 + //---------------------------------------------------------------------------------- + // Emit new particles: when emissionRate is 1, emit every frame + if (emissionRate < 0) + { + if (rand()%(-emissionRate) == 0) + EmitParticle(&circularBuffer, emitterPosition, currentType); + } + else + { + for (int i = 0; i <= emissionRate; ++i) + EmitParticle(&circularBuffer, emitterPosition, currentType); + } + + // Update the parameters of each particle + UpdateParticles(&circularBuffer, screenWidth, screenHeight); + // Remove dead particles from the circular buffer + UpdateCircularBuffer(&circularBuffer); + + // Change Particle Emission Rate (UP/DOWN arrows) + if (IsKeyPressed(KEY_UP)) + ++emissionRate; + if (IsKeyPressed(KEY_DOWN)) + --emissionRate; + + // Change Particle Type (LEFT/RIGHT arrows) + if (IsKeyPressed(KEY_RIGHT)) + (currentType == FIRE) ? (currentType = WATER) : ++currentType; + if (IsKeyPressed(KEY_LEFT)) + (currentType == WATER) ? (currentType = FIRE) : --currentType; + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + emitterPosition = GetMousePosition(); + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Call the function with a loop to draw all particles + DrawParticles(&circularBuffer); + + // Draw UI and Instructions + DrawRectangle(5, 5, 315, 75, Fade(SKYBLUE, 0.5f)); + DrawRectangleLines(5, 5, 315, 75, BLUE); + + DrawText("CONTROLS:", 15, 15, 10, BLACK); + DrawText("UP/DOWN: Change Particle Emission Rate", 15, 35, 10, BLACK); + DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK); + + if (emissionRate < 0) + DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypesChar[currentType]), 15, 95, 10, DARKGRAY); + else + DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypesChar[currentType]), 15, 95, 10, DARKGRAY); + + DrawFPS(screenWidth - 80, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + RL_FREE(particles); // Free particles array data + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition, ParticleType type) +{ + Particle *newParticle = AddToCircularBuffer(circularBuffer); + // If buffer is full, newParticle is NULL + if (newParticle != NULL) + { + // Fill particle properties + newParticle->position = emitterPosition; + newParticle->alive = true; + newParticle->lifeTime = 0.0f; + newParticle->type = type; + float speed = (float)(rand()%10)/5.0f; + switch (type) + { + case WATER: + newParticle->radius = 5.0f; + newParticle->color = BLUE; + break; + case SMOKE: + newParticle->radius = 7.0f; + newParticle->color = GRAY; + break; + case FIRE: + newParticle->radius = 10.0f; + newParticle->color = YELLOW; + speed /= 10.0f; + break; + default: break; + } + float direction = (float)(rand()%360); + newParticle->velocity = (Vector2){ speed*cosf(direction*DEG2RAD), speed*sinf(direction*DEG2RAD) }; + } +} + +static Particle *AddToCircularBuffer(CircularBuffer *circularBuffer) +{ + Particle *particle = NULL; + + // Check if buffer full + if (((circularBuffer->head + 1)%MAX_PARTICLES) != circularBuffer->tail) + { + // Add new particle to the head position and advance head + particle = &circularBuffer->buffer[circularBuffer->head]; + circularBuffer->head = (circularBuffer->head + 1)%MAX_PARTICLES; + } + + return particle; +} + +static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int screenHeight) +{ + for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES) + { + // Update particle life and positions + circularBuffer->buffer[i].lifeTime += 1.0f/60.0f; // 60 FPS -> 1/60 seconds per frame + + switch (circularBuffer->buffer[i].type) + { + case WATER: + circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; + circularBuffer->buffer[i].velocity.y += 0.2f; // Gravity + circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; + break; + case SMOKE: + circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; + circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards + circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; + circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands + circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades + if (circularBuffer->buffer[i].color.a < 4) // If alpha transparent, particle dies + circularBuffer->buffer[i].alive = false; + break; + case FIRE: + // Add a little horizontal oscillation to fire particles + circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f); + circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards + circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; + circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks + circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow + if (circularBuffer->buffer[i].radius <= 0.02f) // If radius too small, particle dies + circularBuffer->buffer[i].alive = false; + break; + default: break; + } + + // Disable particle when out of screen + Vector2 center = circularBuffer->buffer[i].position; + float radius = circularBuffer->buffer[i].radius; + if ((center.x < -radius) || (center.x > screenWidth + radius) || + (center.y < -radius) || (center.y > screenHeight + radius)) + circularBuffer->buffer[i].alive = false; + } +} +static void UpdateCircularBuffer(CircularBuffer *circularBuffer) +{ + // Update circular buffer: advance tail over dead particles + while ((circularBuffer->tail != circularBuffer->head) && + !circularBuffer->buffer[circularBuffer->tail].alive) + { + circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES; + } +} + +static void DrawParticles(CircularBuffer *circularBuffer) +{ + for (int i = circularBuffer->tail; i != circularBuffer->head; i = (i + 1)%MAX_PARTICLES) + { + if (circularBuffer->buffer[i].alive) + { + DrawCircleV(circularBuffer->buffer[i].position, + circularBuffer->buffer[i].radius, + circularBuffer->buffer[i].color); + } + } +} diff --git a/examples/shapes/shapes_simple_particles.png b/examples/shapes/shapes_simple_particles.png new file mode 100644 index 0000000000000000000000000000000000000000..78abece57c0dccecba54c3c679beb9e163d6460a GIT binary patch literal 32265 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 literal 0 HcmV?d00001 diff --git a/projects/VS2022/examples/shapes_simple_particles.vcxproj b/projects/VS2022/examples/shapes_simple_particles.vcxproj new file mode 100644 index 000000000..8a5270503 --- /dev/null +++ b/projects/VS2022/examples/shapes_simple_particles.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {497FDF54-9762-4048-A833-61CC3980A0FB} + Win32Proj + shapes_simple_particles + 10.0 + shapes_simple_particles + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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 881c489ba..48f3762dd 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -383,6 +383,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "ex EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_directory_files", "examples\core_directory_files.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_simple_particles", "examples\shapes_simple_particles.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 From 4ba92f8962ef199ebf85f89b68a40988775de947 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Oct 2025 19:48:36 +0200 Subject: [PATCH 024/102] REVIEWED: Solution when adding new examples --- examples/core/core_directory_files.c | 33 +- examples/core/raygui.h | 5757 +++++++++++++++++ .../examples/core_directory_files.vcxproj | 2 +- .../VS2022/examples/shapes_pie_chart.vcxproj | 2 +- projects/VS2022/raylib.sln | 517 +- 5 files changed, 6059 insertions(+), 252 deletions(-) create mode 100644 examples/core/raygui.h diff --git a/examples/core/core_directory_files.c b/examples/core/core_directory_files.c index 27764315b..b7e11b686 100644 --- a/examples/core/core_directory_files.c +++ b/examples/core/core_directory_files.c @@ -16,12 +16,13 @@ ********************************************************************************************/ #include "raylib.h" -#include // Required for: strcpy() - -#define MAX_FILEPATH_SIZE 2048 #define RAYGUI_IMPLEMENTATION -#include "../shapes/raygui.h" // Required for GUI controls +#include "raygui.h" // Required for GUI controls + +#include // Required for: strcpy() + +#define MAX_FILEPATH_SIZE 2048 //------------------------------------------------------------------------------------ // Program main entry point @@ -37,8 +38,11 @@ int main(void) char directory[MAX_FILEPATH_SIZE] = { 0 }; strcpy(directory, GetWorkingDirectory()); + FilePathList files = LoadDirectoryFiles(directory); + int btnBackPressed = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -46,6 +50,15 @@ int main(void) while (!WindowShouldClose()) // Detect window close button or ESC key { // Update + //---------------------------------------------------------------------------------- + if (btnBackPressed) + { + strcpy(directory, GetPrevDirectoryPath(directory)); + UnloadDirectoryFiles(files); + files = LoadDirectoryFiles(directory); + } + + //---------------------------------------------------------------------------------- // Draw @@ -55,13 +68,8 @@ int main(void) DrawText(directory, 100, 40, 20, DARKGRAY); - if (GuiButton((Rectangle){40.0f, 40.0f, 20, 20}, "<")) - { - strcpy(directory, GetPrevDirectoryPath(directory)); - UnloadDirectoryFiles(files); - files = LoadDirectoryFiles(directory); - } - + btnBackPressed = GuiButton((Rectangle){ 40.0f, 40.0f, 20, 20 }, "<"); + for (int i = 0; i < (int)files.count; i++) { Color color = Fade(LIGHTGRAY, 0.3f); @@ -75,10 +83,11 @@ int main(void) files = LoadDirectoryFiles(directory); } } - DrawRectangle(0, 85 + 40*i, screenWidth, 40, color); + DrawRectangle(0, 85 + 40*i, screenWidth, 40, color); DrawText(GetFileName(files.paths[i]), 120, 100 + 40*i, 10, GRAY); } + EndDrawing(); //---------------------------------------------------------------------------------- } diff --git a/examples/core/raygui.h b/examples/core/raygui.h new file mode 100644 index 000000000..a3fc51f0f --- /dev/null +++ b/examples/core/raygui.h @@ -0,0 +1,5757 @@ +/******************************************************************************************* +* +* 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 +* available as a standalone library, as long as input and drawing functions are provided. +* +* FEATURES: +* - Immediate-mode gui, minimal retained data +* - +25 controls provided (basic and advanced) +* - Styling system for colors, font and metrics +* - Icons supported, embedded as a 1-bit icons pack +* - Standalone mode option (custom input/graphics backend) +* - Multiple support tools provided for raygui development +* +* POSSIBLE IMPROVEMENTS: +* - Better standalone mode API for easy plug of custom backends +* - Externalize required inputs, allow user easier customization +* +* LIMITATIONS: +* - No editable multi-line word-wraped text box supported +* - No auto-layout mechanism, up to the user to define controls position and size +* - Standalone mode requires library modification and some user work to plug another backend +* +* 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 GuiLoadStyleDefault() unloads +* by default any previously loaded font (texture, recs, glyphs). +* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions +* +* CONTROLS PROVIDED: +* # Container/separators Controls +* - WindowBox --> StatusBar, Panel +* - GroupBox --> Line +* - Line +* - Panel --> StatusBar +* - ScrollPanel --> StatusBar +* - TabBar --> Button +* +* # Basic Controls +* - Label +* - LabelButton --> Label +* - Button +* - Toggle +* - ToggleGroup --> Toggle +* - ToggleSlider +* - CheckBox +* - ComboBox +* - DropdownBox +* - TextBox +* - ValueBox --> TextBox +* - Spinner --> Button, ValueBox +* - Slider +* - SliderBar --> Slider +* - ProgressBar +* - StatusBar +* - DummyRec +* - Grid +* +* # Advance Controls +* - ListView +* - ColorPicker --> ColorPanel, ColorBarHue +* - MessageBox --> Window, Label, Button +* - TextInputBox --> Window, Label, TextBox, Button +* +* It also provides a set of functions for styling the controls based on its properties (size, color). +* +* +* RAYGUI STYLE (guiStyle): +* raygui uses a global data array for all gui style properties (allocated on data segment by default), +* when a new style is loaded, it is loaded over the global style... but a default gui style could always be +* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one +* +* The global style array size is fixed and depends on the number of controls and properties: +* +* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)]; +* +* guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +* +* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style +* used for all controls, when any of those base values is set, it is automatically populated to all +* controls, so, specific control values overwriting generic style should be set after base values. +* +* After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those +* properties are actually common to all controls and can not be overwritten individually (like BASE ones) +* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR +* +* Custom control properties can be defined using the EXTENDED properties for each independent control. +* +* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler +* +* +* RAYGUI ICONS (guiIcons): +* raygui could use a global array containing icons data (allocated on data segment by default), +* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set +* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded +* +* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon +* requires 8 integers (16*16/32) to be stored in memory. +* +* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set. +* +* The global icons array size is fixed and depends on the number of icons and size: +* +* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS]; +* +* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +* +* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons +* +* RAYGUI LAYOUT: +* raygui currently does not provide an auto-layout mechanism like other libraries, +* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it. +* +* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout +* +* CONFIGURATION: +* #define RAYGUI_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* #define RAYGUI_STANDALONE +* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined +* internally in the library and input management and drawing functions must be provided by +* the user (check library implementation for further details). +* +* #define RAYGUI_NO_ICONS +* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB) +* +* #define RAYGUI_CUSTOM_ICONS +* Includes custom ricons.h header defining a set of custom icons, +* this file can be generated using rGuiIcons tool +* +* #define RAYGUI_DEBUG_RECS_BOUNDS +* Draw control bounds rectangles for debug +* +* #define RAYGUI_DEBUG_TEXT_BOUNDS +* 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 +* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE +* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode +* ADDED: Support loading styles with custom font charset from external file +* REDESIGNED: GuiTextBox(), support mouse cursor positioning +* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only) +* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color +* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText() +* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value +* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value +* REDESIGNED: GuiComboBox(), get parameters by reference and return result value +* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value +* REDESIGNED: GuiSlider(), get parameters by reference and return result value +* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value +* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value +* REDESIGNED: GuiListView(), get parameters by reference and return result value +* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value +* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), added extra parameter +* REDESIGNED: GuiListViewEx(), change parameters order +* REDESIGNED: All controls return result as int value +* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars +* REVIEWED: All examples and specially controls_test_suite +* RENAMED: gui_file_dialog module to gui_window_file_dialog +* UPDATED: All styles to include ISO-8859-15 charset (as much as possible) +* +* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER +* ADDED: GuiLoadStyleFromMemory() (binary only) +* REVIEWED: GuiScrollBar() horizontal movement key +* REVIEWED: GuiTextBox() crash on cursor movement +* REVIEWED: GuiTextBox(), additional inputs support +* REVIEWED: GuiLabelButton(), avoid text cut +* REVIEWED: GuiTextInputBox(), password input +* REVIEWED: Local GetCodepointNext(), aligned with raylib +* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds +* +* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle() +* ADDED: Helper functions to split text in separate lines +* ADDED: Multiple new icons, useful for code editing tools +* REMOVED: Unneeded icon editing functions +* REMOVED: GuiTextBoxMulti(), very limited and broken +* REMOVED: MeasureTextEx() dependency, logic directly implemented +* REMOVED: DrawTextEx() dependency, logic directly implemented +* REVIEWED: GuiScrollBar(), improve mouse-click behaviour +* REVIEWED: Library header info, more info, better organized +* REDESIGNED: GuiTextBox() to support cursor movement +* REDESIGNED: GuiDrawText() to divide drawing by lines +* +* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes +* REMOVED: GuiScrollBar(), only internal +* REDESIGNED: GuiPanel() to support text parameter +* REDESIGNED: GuiScrollPanel() to support text parameter +* REDESIGNED: GuiColorPicker() to support text parameter +* REDESIGNED: GuiColorPanel() to support text parameter +* REDESIGNED: GuiColorBarAlpha() to support text parameter +* REDESIGNED: GuiColorBarHue() to support text parameter +* REDESIGNED: GuiTextInputBox() to support password +* +* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool) +* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures +* REVIEWED: External icons usage logic +* REVIEWED: GuiLine() for centered alignment when including text +* RENAMED: Multiple controls properties definitions to prepend RAYGUI_ +* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency +* Projects updated and multiple tweaks +* +* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file +* REDESIGNED: GuiTextBoxMulti() +* REMOVED: GuiImageButton*() +* Multiple minor tweaks and bugs corrected +* +* 2.9 (17-Mar-2021) REMOVED: Tooltip API +* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle() +* 2.7 (20-Feb-2020) ADDED: Possible tooltips API +* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox() +* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox() +* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle() +* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties +* ADDED: 8 new custom styles ready to use +* Multiple minor tweaks and bugs corrected +* +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* REDESIGNED: Style system (breaking change) +* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts +* REVIEWED: GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout +* 1.5 (21-Jun-2017) Working in an improved styles system +* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) +* 1.3 (12-Jun-2017) Complete redesign of style system +* 1.1 (01-Jun-2017) Complete review of the library +* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria. +* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria. +* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria. +* +* DEPENDENCIES: +* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* +* STANDALONE MODE: +* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled +* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs. +* +* The following functions should be redefined for a custom backend: +* +* - Vector2 GetMousePosition(void); +* - float GetMouseWheelMove(void); +* - bool IsMouseButtonDown(int button); +* - bool IsMouseButtonPressed(int button); +* - bool IsMouseButtonReleased(int button); +* - bool IsKeyDown(int key); +* - bool IsKeyPressed(int key); +* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +* +* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +* +* - Font GetFontDefault(void); // -- GuiLoadStyleDefault() +* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle() +* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) +* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data +* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs +* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list +* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, redesign, update and maintenance +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) +* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) +* Adria Arranz: Testing and implementation of additional controls (2018) +* Jordi Jorba: Testing and implementation of additional controls (2018) +* Albert Martos: Review and testing of the library (2015) +* Ian Eito: Review and testing of the library (2015) +* Kevin Gato: Initial implementation of basic components (2014) +* Daniel Nicolas: Initial implementation of basic components (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYGUI_H +#define RAYGUI_H + +#define RAYGUI_VERSION_MAJOR 4 +#define RAYGUI_VERSION_MINOR 5 +#define RAYGUI_VERSION_PATCH 0 +#define RAYGUI_VERSION "4.5-dev" + +#if !defined(RAYGUI_STANDALONE) + #include "raylib.h" +#endif + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) + #endif +#endif + +// Function specifiers definition +#ifndef RAYGUIAPI + #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Allow custom memory allocators +#ifndef RAYGUI_MALLOC + #define RAYGUI_MALLOC(sz) malloc(sz) +#endif +#ifndef RAYGUI_CALLOC + #define RAYGUI_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RAYGUI_FREE + #define RAYGUI_FREE(p) free(p) +#endif + +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define RAYGUI_SUPPORT_LOG_INFO +#if defined(RAYGUI_SUPPORT_LOG_INFO) + #define RAYGUI_LOG(...) printf(__VA_ARGS__) +#else + #define RAYGUI_LOG(...) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Some types are required for RAYGUI_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + #ifndef __cplusplus + // Boolean type + #ifndef true + typedef enum { false, true } bool; + #endif + #endif + + // Vector2 type + typedef struct Vector2 { + float x; + float y; + } Vector2; + + // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV() + typedef struct Vector3 { + float x; + float y; + float z; + } Vector3; + + // Color type, RGBA (32bit) + typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } Color; + + // Rectangle type + typedef struct Rectangle { + float x; + float y; + float width; + float height; + } Rectangle; + + // TODO: Texture2D type is very coupled to raylib, required by Font type + // It should be redesigned to be provided by user + typedef struct Texture2D { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Texture2D; + + // Image, pixel data stored in CPU memory (RAM) + typedef struct Image { + void *data; // Image raw data + int width; // Image base width + int height; // Image base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Image; + + // GlyphInfo, font characters glyphs info + typedef struct GlyphInfo { + int value; // Character value (Unicode) + int offsetX; // Character offset X when drawing + int offsetY; // Character offset Y when drawing + int advanceX; // Character advance position X + Image image; // Character image data + } GlyphInfo; + + // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle() + // It should be redesigned to be provided by user + typedef struct Font { + int baseSize; // Base size (default chars height) + int glyphCount; // Number of glyph characters + int glyphPadding; // Padding around the glyph characters + Texture2D texture; // Texture atlas containing the glyphs + Rectangle *recs; // Rectangles in texture for the glyphs + GlyphInfo *glyphs; // Glyphs info data + } Font; +#endif + +// Style property +// NOTE: Used when exporting style as code for convenience +typedef struct GuiStyleProp { + unsigned short controlId; // Control identifier + unsigned short propertyId; // Property identifier + int propertyValue; // Property value +} GuiStyleProp; + +/* +// Controls text style -NOT USED- +// NOTE: Text style is defined by control +typedef struct GuiTextStyle { + unsigned int size; + int charSpacing; + int lineSpacing; + int alignmentH; + int alignmentV; + int padding; +} GuiTextStyle; +*/ + +// Gui control state +typedef enum { + STATE_NORMAL = 0, + STATE_FOCUSED, + STATE_PRESSED, + STATE_DISABLED +} GuiState; + +// Gui control text alignment +typedef enum { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT +} GuiTextAlignment; + +// Gui control text alignment vertical +// NOTE: Text vertical position inside the text bounds +typedef enum { + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_MIDDLE, + TEXT_ALIGN_BOTTOM +} GuiTextAlignmentVertical; + +// Gui control text wrap mode +// NOTE: Useful for multiline text +typedef enum { + TEXT_WRAP_NONE = 0, + TEXT_WRAP_CHAR, + TEXT_WRAP_WORD +} GuiTextWrapMode; + +// Gui controls +typedef enum { + // Default -> populates to all controls when set + DEFAULT = 0, + + // Basic controls + LABEL, // Used also for: LABELBUTTON + BUTTON, + TOGGLE, // Used also for: TOGGLEGROUP + SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER + PROGRESSBAR, + CHECKBOX, + COMBOBOX, + DROPDOWNBOX, + TEXTBOX, // Used also for: TEXTBOXMULTI + VALUEBOX, + SPINNER, // Uses: BUTTON, VALUEBOX + LISTVIEW, + COLORPICKER, + SCROLLBAR, + STATUSBAR +} GuiControl; + +// Gui base properties for every control +// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties) +typedef enum { + BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL + BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL + TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL + BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED + BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED + TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED + BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED + BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED + TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED + BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED + BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED + TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED + BORDER_WIDTH, // Control border size, 0 for no border + //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls + //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls + //TEXT_LINE_SPACING // Control text spacing between lines -> GLOBAL for all controls + TEXT_PADDING, // Control text padding, not considering border + TEXT_ALIGNMENT, // Control text horizontal alignment inside control text bound (after border and padding) + //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls +} GuiControlProperty; + +// TODO: Which text styling properties should be global or per-control? +// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while +// 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) +//---------------------------------------------------------------------------------- +// DEFAULT extended properties +// NOTE: Those properties are common to all controls or global +// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT? +typedef enum { + TEXT_SIZE = 16, // Text size (glyphs max height) + TEXT_SPACING, // Text spacing between glyphs + LINE_COLOR, // Line control color + BACKGROUND_COLOR, // Background color + TEXT_LINE_SPACING, // Text spacing between lines + 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 thickness +} GuiDefaultProperty; + +// Other possible text properties: +// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... + +// Label +//typedef enum { } GuiLabelProperty; + +// Button/Spinner +//typedef enum { } GuiButtonProperty; + +// Toggle/ToggleGroup +typedef enum { + GROUP_PADDING = 16, // ToggleGroup separation between toggles +} GuiToggleProperty; + +// Slider/SliderBar +typedef enum { + SLIDER_WIDTH = 16, // Slider size of internal bar + SLIDER_PADDING // Slider/SliderBar internal bar padding +} GuiSliderProperty; + +// ProgressBar +typedef enum { + PROGRESS_PADDING = 16, // ProgressBar internal padding +} GuiProgressBarProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, // ScrollBar arrows size + ARROWS_VISIBLE, // ScrollBar arrows visible + SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding + SCROLL_SLIDER_SIZE, // ScrollBar slider size + SCROLL_PADDING, // ScrollBar scroll padding from arrows + SCROLL_SPEED, // ScrollBar scrolling speed +} GuiScrollBarProperty; + +// CheckBox +typedef enum { + CHECK_PADDING = 16 // CheckBox internal check padding +} GuiCheckBoxProperty; + +// ComboBox +typedef enum { + COMBO_BUTTON_WIDTH = 16, // ComboBox right button width + COMBO_BUTTON_SPACING // ComboBox button separation +} GuiComboBoxProperty; + +// DropdownBox +typedef enum { + ARROW_PADDING = 16, // DropdownBox arrow separation from border and items + 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 +typedef enum { + TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable +} GuiTextBoxProperty; + +// Spinner +typedef enum { + SPIN_BUTTON_WIDTH = 16, // Spinner left/right buttons width + SPIN_BUTTON_SPACING, // Spinner buttons separation +} GuiSpinnerProperty; + +// ListView +typedef enum { + LIST_ITEMS_HEIGHT = 16, // ListView items height + 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 +typedef enum { + COLOR_SELECTOR_SIZE = 16, + HUEBAR_WIDTH, // ColorPicker right hue bar width + HUEBAR_PADDING, // ColorPicker right hue bar separation from panel + HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height + HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow +} GuiColorPickerProperty; + +#define SCROLLBAR_LEFT_SIDE 0 +#define SCROLLBAR_RIGHT_SIDE 1 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Global gui state control functions +RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state) +RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state) +RAYGUIAPI void GuiLock(void); // Lock gui controls (global state) +RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state) +RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state) +RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f +RAYGUIAPI void GuiSetState(int state); // Set gui state (global state) +RAYGUIAPI int GuiGetState(void); // Get gui state (global state) + +// Font set/get functions +RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state) +RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state) + +// Style set/get functions +RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property +RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property + +// Styles loading functions +RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs) +RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style + +// Tooltips management functions +RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state) +RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state) +RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string + +// Icons functionality +RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported) +#if !defined(RAYGUI_NO_ICONS) +RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size +RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer +RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data +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 +RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed +RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name +RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text +RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls +RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 +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 +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, 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 + +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 +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 + +// Advance controls set +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 +RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) +RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control +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 updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() +//---------------------------------------------------------------------------------------------------------- + +#if !defined(RAYGUI_NO_ICONS) + +#if !defined(RAYGUI_CUSTOM_ICONS) +//---------------------------------------------------------------------------------- +// Icons enumeration +//---------------------------------------------------------------------------------- +typedef enum { + ICON_NONE = 0, + ICON_FOLDER_FILE_OPEN = 1, + ICON_FILE_SAVE_CLASSIC = 2, + ICON_FOLDER_OPEN = 3, + ICON_FOLDER_SAVE = 4, + ICON_FILE_OPEN = 5, + ICON_FILE_SAVE = 6, + ICON_FILE_EXPORT = 7, + ICON_FILE_ADD = 8, + ICON_FILE_DELETE = 9, + ICON_FILETYPE_TEXT = 10, + ICON_FILETYPE_AUDIO = 11, + ICON_FILETYPE_IMAGE = 12, + ICON_FILETYPE_PLAY = 13, + ICON_FILETYPE_VIDEO = 14, + ICON_FILETYPE_INFO = 15, + ICON_FILE_COPY = 16, + ICON_FILE_CUT = 17, + ICON_FILE_PASTE = 18, + ICON_CURSOR_HAND = 19, + ICON_CURSOR_POINTER = 20, + ICON_CURSOR_CLASSIC = 21, + ICON_PENCIL = 22, + ICON_PENCIL_BIG = 23, + ICON_BRUSH_CLASSIC = 24, + ICON_BRUSH_PAINTER = 25, + ICON_WATER_DROP = 26, + ICON_COLOR_PICKER = 27, + ICON_RUBBER = 28, + ICON_COLOR_BUCKET = 29, + ICON_TEXT_T = 30, + ICON_TEXT_A = 31, + ICON_SCALE = 32, + ICON_RESIZE = 33, + ICON_FILTER_POINT = 34, + ICON_FILTER_BILINEAR = 35, + ICON_CROP = 36, + ICON_CROP_ALPHA = 37, + ICON_SQUARE_TOGGLE = 38, + ICON_SYMMETRY = 39, + ICON_SYMMETRY_HORIZONTAL = 40, + ICON_SYMMETRY_VERTICAL = 41, + ICON_LENS = 42, + ICON_LENS_BIG = 43, + ICON_EYE_ON = 44, + ICON_EYE_OFF = 45, + ICON_FILTER_TOP = 46, + ICON_FILTER = 47, + ICON_TARGET_POINT = 48, + ICON_TARGET_SMALL = 49, + ICON_TARGET_BIG = 50, + ICON_TARGET_MOVE = 51, + ICON_CURSOR_MOVE = 52, + ICON_CURSOR_SCALE = 53, + ICON_CURSOR_SCALE_RIGHT = 54, + ICON_CURSOR_SCALE_LEFT = 55, + ICON_UNDO = 56, + ICON_REDO = 57, + ICON_REREDO = 58, + ICON_MUTATE = 59, + ICON_ROTATE = 60, + ICON_REPEAT = 61, + ICON_SHUFFLE = 62, + ICON_EMPTYBOX = 63, + ICON_TARGET = 64, + ICON_TARGET_SMALL_FILL = 65, + ICON_TARGET_BIG_FILL = 66, + ICON_TARGET_MOVE_FILL = 67, + ICON_CURSOR_MOVE_FILL = 68, + ICON_CURSOR_SCALE_FILL = 69, + ICON_CURSOR_SCALE_RIGHT_FILL = 70, + ICON_CURSOR_SCALE_LEFT_FILL = 71, + ICON_UNDO_FILL = 72, + ICON_REDO_FILL = 73, + ICON_REREDO_FILL = 74, + ICON_MUTATE_FILL = 75, + ICON_ROTATE_FILL = 76, + ICON_REPEAT_FILL = 77, + ICON_SHUFFLE_FILL = 78, + ICON_EMPTYBOX_SMALL = 79, + ICON_BOX = 80, + ICON_BOX_TOP = 81, + ICON_BOX_TOP_RIGHT = 82, + ICON_BOX_RIGHT = 83, + ICON_BOX_BOTTOM_RIGHT = 84, + ICON_BOX_BOTTOM = 85, + ICON_BOX_BOTTOM_LEFT = 86, + ICON_BOX_LEFT = 87, + ICON_BOX_TOP_LEFT = 88, + ICON_BOX_CENTER = 89, + ICON_BOX_CIRCLE_MASK = 90, + ICON_POT = 91, + ICON_ALPHA_MULTIPLY = 92, + ICON_ALPHA_CLEAR = 93, + ICON_DITHERING = 94, + ICON_MIPMAPS = 95, + ICON_BOX_GRID = 96, + ICON_GRID = 97, + ICON_BOX_CORNERS_SMALL = 98, + ICON_BOX_CORNERS_BIG = 99, + ICON_FOUR_BOXES = 100, + ICON_GRID_FILL = 101, + ICON_BOX_MULTISIZE = 102, + ICON_ZOOM_SMALL = 103, + ICON_ZOOM_MEDIUM = 104, + ICON_ZOOM_BIG = 105, + ICON_ZOOM_ALL = 106, + ICON_ZOOM_CENTER = 107, + ICON_BOX_DOTS_SMALL = 108, + ICON_BOX_DOTS_BIG = 109, + ICON_BOX_CONCENTRIC = 110, + ICON_BOX_GRID_BIG = 111, + ICON_OK_TICK = 112, + ICON_CROSS = 113, + ICON_ARROW_LEFT = 114, + ICON_ARROW_RIGHT = 115, + ICON_ARROW_DOWN = 116, + ICON_ARROW_UP = 117, + ICON_ARROW_LEFT_FILL = 118, + ICON_ARROW_RIGHT_FILL = 119, + ICON_ARROW_DOWN_FILL = 120, + ICON_ARROW_UP_FILL = 121, + ICON_AUDIO = 122, + ICON_FX = 123, + ICON_WAVE = 124, + ICON_WAVE_SINUS = 125, + ICON_WAVE_SQUARE = 126, + ICON_WAVE_TRIANGULAR = 127, + ICON_CROSS_SMALL = 128, + ICON_PLAYER_PREVIOUS = 129, + ICON_PLAYER_PLAY_BACK = 130, + ICON_PLAYER_PLAY = 131, + ICON_PLAYER_PAUSE = 132, + ICON_PLAYER_STOP = 133, + ICON_PLAYER_NEXT = 134, + ICON_PLAYER_RECORD = 135, + ICON_MAGNET = 136, + ICON_LOCK_CLOSE = 137, + ICON_LOCK_OPEN = 138, + ICON_CLOCK = 139, + ICON_TOOLS = 140, + ICON_GEAR = 141, + ICON_GEAR_BIG = 142, + ICON_BIN = 143, + ICON_HAND_POINTER = 144, + ICON_LASER = 145, + ICON_COIN = 146, + ICON_EXPLOSION = 147, + ICON_1UP = 148, + ICON_PLAYER = 149, + ICON_PLAYER_JUMP = 150, + ICON_KEY = 151, + ICON_DEMON = 152, + ICON_TEXT_POPUP = 153, + ICON_GEAR_EX = 154, + ICON_CRACK = 155, + ICON_CRACK_POINTS = 156, + ICON_STAR = 157, + ICON_DOOR = 158, + ICON_EXIT = 159, + ICON_MODE_2D = 160, + ICON_MODE_3D = 161, + ICON_CUBE = 162, + ICON_CUBE_FACE_TOP = 163, + ICON_CUBE_FACE_LEFT = 164, + ICON_CUBE_FACE_FRONT = 165, + ICON_CUBE_FACE_BOTTOM = 166, + ICON_CUBE_FACE_RIGHT = 167, + ICON_CUBE_FACE_BACK = 168, + ICON_CAMERA = 169, + ICON_SPECIAL = 170, + ICON_LINK_NET = 171, + ICON_LINK_BOXES = 172, + ICON_LINK_MULTI = 173, + ICON_LINK = 174, + ICON_LINK_BROKE = 175, + ICON_TEXT_NOTES = 176, + ICON_NOTEBOOK = 177, + ICON_SUITCASE = 178, + ICON_SUITCASE_ZIP = 179, + ICON_MAILBOX = 180, + ICON_MONITOR = 181, + ICON_PRINTER = 182, + ICON_PHOTO_CAMERA = 183, + ICON_PHOTO_CAMERA_FLASH = 184, + ICON_HOUSE = 185, + ICON_HEART = 186, + ICON_CORNER = 187, + ICON_VERTICAL_BARS = 188, + ICON_VERTICAL_BARS_FILL = 189, + ICON_LIFE_BARS = 190, + ICON_INFO = 191, + ICON_CROSSLINE = 192, + ICON_HELP = 193, + ICON_FILETYPE_ALPHA = 194, + ICON_FILETYPE_HOME = 195, + ICON_LAYERS_VISIBLE = 196, + ICON_LAYERS = 197, + ICON_WINDOW = 198, + ICON_HIDPI = 199, + ICON_FILETYPE_BINARY = 200, + ICON_HEX = 201, + ICON_SHIELD = 202, + ICON_FILE_NEW = 203, + ICON_FOLDER_ADD = 204, + ICON_ALARM = 205, + ICON_CPU = 206, + ICON_ROM = 207, + ICON_STEP_OVER = 208, + ICON_STEP_INTO = 209, + ICON_STEP_OUT = 210, + ICON_RESTART = 211, + ICON_BREAKPOINT_ON = 212, + ICON_BREAKPOINT_OFF = 213, + ICON_BURGER_MENU = 214, + ICON_CASE_SENSITIVE = 215, + ICON_REG_EXP = 216, + ICON_FOLDER = 217, + ICON_FILE = 218, + ICON_SAND_TIMER = 219, + 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_HOT = 228, + ICON_229 = 229, + ICON_230 = 230, + ICON_231 = 231, + ICON_232 = 232, + ICON_233 = 233, + ICON_234 = 234, + ICON_235 = 235, + ICON_236 = 236, + ICON_237 = 237, + ICON_238 = 238, + ICON_239 = 239, + ICON_240 = 240, + ICON_241 = 241, + ICON_242 = 242, + ICON_243 = 243, + ICON_244 = 244, + ICON_245 = 245, + ICON_246 = 246, + ICON_247 = 247, + ICON_248 = 248, + ICON_249 = 249, + ICON_250 = 250, + ICON_251 = 251, + ICON_252 = 252, + ICON_253 = 253, + ICON_254 = 254, + ICON_255 = 255, +} GuiIconName; +#endif + +#endif + +#if defined(__cplusplus) +} // Prevents name mangling of functions +#endif + +#endif // RAYGUI_H + +/*********************************************************************************** +* +* RAYGUI IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RAYGUI_IMPLEMENTATION) + +#include // required for: isspace() [GuiTextBox()] +#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() +#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()] +#include // Required for: roundf() [GuiColorPicker()] + +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + +// Check if two rectangles are equal, used to validate a slider bounds as an id +#ifndef CHECK_BOUNDS_ID + #define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height)) +#endif + +#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS) + +// Embedded icons, no external file provided +#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared) +#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons +#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id + +// Icons data is defined by bit array (every bit represents one pixel) +// Those arrays are stored as unsigned int data arrays, so, +// every array element defines 32 pixels (bits) of information +// One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels) +// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels) +#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32) + +//---------------------------------------------------------------------------------- +// Icons data for all gui possible icons (allocated on data segment by default) +// +// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so, +// every 16x16 icon requires 8 integers (16*16/32) to be stored +// +// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(), +// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS +// +// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +//---------------------------------------------------------------------------------- +static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE + 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN + 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE + 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT + 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO + 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE + 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY + 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO + 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO + 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY + 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT + 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE + 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND + 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER + 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC + 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL + 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG + 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC + 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER + 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP + 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER + 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER + 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET + 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T + 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A + 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE + 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE + 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT + 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR + 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP + 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA + 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE + 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY + 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL + 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL + 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS + 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG + 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON + 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF + 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP + 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER + 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT + 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL + 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG + 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE + 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE + 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE + 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT + 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT + 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO + 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE + 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT + 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE + 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX + 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET + 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL + 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL + 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL + 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL + 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL + 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL + 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL + 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL + 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL + 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX + 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP + 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT + 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER + 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK + 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR + 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING + 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS + 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID + 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID + 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL + 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG + 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES + 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL + 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE + 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL + 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM + 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG + 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL + 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER + 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL + 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG + 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC + 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG + 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK + 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS + 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT + 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT + 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN + 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP + 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL + 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL + 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL + 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL + 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO + 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX + 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE + 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS + 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE + 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR + 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL + 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS + 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK + 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY + 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE + 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP + 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT + 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD + 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET + 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE + 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN + 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK + 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS + 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR + 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG + 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN + 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER + 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER + 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN + 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION + 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP + 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER + 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP + 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY + 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON + 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP + 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX + 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK + 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS + 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR + 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR + 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT + 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D + 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE + 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP + 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM + 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT + 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK + 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA + 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL + 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET + 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES + 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI + 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK + 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE + 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES + 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK + 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE + 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP + 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX + 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR + 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER + 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA + 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH + 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE + 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER + 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS + 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL + 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS + 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO + 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE + 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP + 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA + 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME + 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE + 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS + 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW + 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI + 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY + 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX + 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD + 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW + 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD + 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM + 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU + 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM + 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER + 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO + 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT + 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART + 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON + 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF + 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU + 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE + 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP + 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 + 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 + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_232 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_233 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 +}; + +// NOTE: A pointer to current icons array should be defined +static unsigned int *guiIconsPtr = guiIcons; + +#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS + +#ifndef RAYGUI_ICON_SIZE + #define RAYGUI_ICON_SIZE 0 +#endif + +// WARNING: Those values define the total size of the style data array, +// if changed, previous saved styles could become incompatible +#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls +#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties +#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// Gui control property style color element +typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state + +static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib) +static bool guiLocked = false; // Gui lock state (no inputs processed) +static float guiAlpha = 1.0f; // Gui controls transparency + +static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled) + +static bool guiTooltip = false; // Tooltip enabled/disabled +static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) + +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 +static int autoCursorCooldownCounter = 0; // Cooldown frame counter for automatic cursor movement on key-down +static int autoCursorDelayCounter = 0; // Delay frame counter for automatic cursor movement + +//---------------------------------------------------------------------------------- +// Style data array for all gui style properties (allocated on data segment by default) +// +// NOTE 1: First set of BASE properties are generic to all controls but could be individually +// overwritten per control, first set of EXTENDED properties are generic to all controls and +// can not be overwritten individually but custom EXTENDED properties can be used by control +// +// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(), +// but default gui style could always be recovered with GuiLoadStyleDefault() +// +// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +//---------------------------------------------------------------------------------- +static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 }; + +static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization + +//---------------------------------------------------------------------------------- +// Standalone Mode Functions Declaration +// +// NOTE: raygui depend on some raylib input and drawing functions +// To use raygui as standalone library, below functions must be defined by the user +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + +#define KEY_RIGHT 262 +#define KEY_LEFT 263 +#define KEY_DOWN 264 +#define KEY_UP 265 +#define KEY_BACKSPACE 259 +#define KEY_ENTER 257 + +#define MOUSE_LEFT_BUTTON 0 + +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static float GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); + +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +//------------------------------------------------------------------------------- + +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font + +static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) + +static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data + +static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs + +static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list + +static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui +//------------------------------------------------------------------------------- +static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value +static int ColorToInt(Color color); // Returns hexadecimal value for a Color +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +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) + +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient +//------------------------------------------------------------------------------- + +#endif // RAYGUI_STANDALONE + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only) + +static int GetTextWidth(const char *text); // Gui get text width using gui font and style +static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds +static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor + +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style + +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings +static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB +static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV + +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel() +static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position + +static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor + +//---------------------------------------------------------------------------------- +// Gui Setup Functions Definition +//---------------------------------------------------------------------------------- +// Enable gui global state +// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups +void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; } + +// Disable gui global state +// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups +void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; } + +// Lock gui global state +void GuiLock(void) { guiLocked = true; } + +// Unlock gui global state +void GuiUnlock(void) { guiLocked = false; } + +// Check if gui is locked (global state) +bool GuiIsLocked(void) { return guiLocked; } + +// Set gui controls alpha global state +void GuiSetAlpha(float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + guiAlpha = alpha; +} + +// Set gui state (global state) +void GuiSetState(int state) { guiState = (GuiState)state; } + +// Get gui state (global state) +int GuiGetState(void) { return guiState; } + +// Set custom gui font +// NOTE: Font loading/unloading is external to raygui +void GuiSetFont(Font font) +{ + if (font.texture.id > 0) + { + // NOTE: If we try to setup a font but default style has not been + // lazily loaded before, it will be overwritten, so we need to force + // default style loading first + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + guiFont = font; + } +} + +// Get custom gui font +Font GuiGetFont(void) +{ + return guiFont; +} + +// Set control style property value +void GuiSetStyle(int control, int property, int value) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + + // Default properties are propagated to all controls + if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE)) + { + for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + } +} + +// Get control style property value +int GuiGetStyle(int control, int property) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property]; +} + +//---------------------------------------------------------------------------------- +// Gui Controls Functions Definition +//---------------------------------------------------------------------------------- + +// Window Box control +int GuiWindowBox(Rectangle bounds, const char *title) +{ + // Window title bar height (including borders) + // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox() + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + int result = 0; + //GuiState state = guiState; + + int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight }; + if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f; + + Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 }; + Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20, + statusBar.y + statusBarHeight/2.0f - 18.0f/2.0f, 18, 18 }; + + // Update control + //-------------------------------------------------------------------- + // NOTE: Logic is directly managed by button + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiStatusBar(statusBar, title); // Draw window header as status bar + GuiPanel(windowPanel, NULL); // Draw window base + + // Draw window close button + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + result = GuiButton(closeButtonRec, "x"); +#else + result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL)); +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + //-------------------------------------------------------------------- + + return result; // Window close button clicked: result = 1 +} + +// Group Box control with text name +int GuiGroupBox(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_GROUPBOX_LINE_THICK) + #define RAYGUI_GROUPBOX_LINE_THICK 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); + //-------------------------------------------------------------------- + + return result; +} + +// Line control +int GuiLine(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_LINE_ORIGIN_SIZE) + #define RAYGUI_LINE_MARGIN_TEXT 12 + #endif + #if !defined(RAYGUI_LINE_TEXT_PADDING) + #define RAYGUI_LINE_TEXT_PADDING 4 + #endif + + int result = 0; + GuiState state = guiState; + + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); + + // Draw control + //-------------------------------------------------------------------- + if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color); + else + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = bounds.height; + textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT; + textBounds.y = bounds.y; + + // Draw line with embedded text label: "--- text --------------" + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + } + //-------------------------------------------------------------------- + + return result; +} + +// Panel control +int GuiPanel(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_PANEL_BORDER_WIDTH) + #define RAYGUI_PANEL_BORDER_WIDTH 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + } + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)), + GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR))); + //-------------------------------------------------------------------- + + return result; +} + +// Tab Bar control +// NOTE: Using GuiToggle() for the TABS +int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) +{ + #define RAYGUI_TABBAR_ITEM_WIDTH 160 + + int result = -1; + //GuiState state = guiState; + + Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height }; + + if (*active < 0) *active = 0; + else if (*active > count - 1) *active = count - 1; + + int offsetX = 0; // Required in case tabs go out of screen + offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth(); + if (offsetX < 0) offsetX = 0; + + bool toggle = false; // Required for individual toggles + + // Draw control + //-------------------------------------------------------------------- + for (int i = 0; i < count; i++) + { + tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX; + + if (tabBounds.x < GetScreenWidth()) + { + // Draw tabs as toggle controls + int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT); + int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(TOGGLE, TEXT_PADDING, 8); + + if (i == (*active)) + { + toggle = true; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + } + else + { + toggle = false; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + 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); + + // Draw tab close button + // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds)) + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i; +#else + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i; +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + } + } + + // Draw tab-bar bottom line + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL))); + //-------------------------------------------------------------------- + + return result; // Return as result the current TAB closing requested +} + +// Scroll Panel control +int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view) +{ + #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; + + Rectangle temp = { 0 }; + if (view == NULL) view = &temp; + + Vector2 scrollPos = { 0.0f, 0.0f }; + if (scroll != NULL) scrollPos = *scroll; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1; + } + + bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + + // Recheck to account for the other scrollbar being visible + if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + + int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth + }; + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Make sure scroll bars have a minimum width/height + 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)? + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + + // Clip view area to the actual content size + if (view->width > content.width) view->width = content.width; + if (view->height > content.height) view->height = content.height; + + float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH); + float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f; + float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + +#if defined(SUPPORT_SCROLLBAR_KEY_INPUT) + if (hasHorizontalScrollBar) + { + if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } + + if (hasVerticalScrollBar) + { + if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } +#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.x; + else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll + } + } + + // Normalize scroll values + if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin; + if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax; + if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin; + if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Save size of the scrollbar slider + const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + + // Draw horizontal scrollbar if visible + if (hasHorizontalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content width and the widget width + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth))); + scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax); + } + else scrollPos.x = 0.0f; + + // Draw vertical scrollbar if visible + if (hasVerticalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content height and the widget height + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth))); + scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax); + } + else scrollPos.y = 0.0f; + + // Draw detail corner rectangle if both scroll bars are visible + if (hasHorizontalScrollBar && hasVerticalScrollBar) + { + Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 }; + GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3)))); + } + + // Draw scrollbar lines depending on current state + 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); + //-------------------------------------------------------------------- + + if (scroll != NULL) *scroll = scrollPos; + + return result; +} + +// Label control +int GuiLabel(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + //... + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Button control, returns true when clicked +int GuiButton(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3)))); + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //------------------------------------------------------------------ + + return result; // Button pressed: result = 1 +} + +// Label button control +int GuiLabelButton(Rectangle bounds, const char *text) +{ + GuiState state = guiState; + bool pressed = false; + + // NOTE: We force bounds.width to be all text + float textWidth = (float)GetTextWidth(text); + if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return pressed; +} + +// Toggle Button control +int GuiToggle(Rectangle bounds, const char *text, bool *active) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (active == NULL) active = &temp; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check toggle button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_NORMAL; + *active = !(*active); + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_NORMAL) + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3))))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3))))); + } + else + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3))); + } + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; +} + +// Toggle Group control +int GuiToggleGroup(Rectangle bounds, const char *text, int *active) +{ + #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) + #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32 + #endif + + int result = 0; + float initBoundsX = bounds.x; + + int temp = 0; + if (active == NULL) active = &temp; + + bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, rows); + + int prevRow = rows[0]; + + for (int i = 0; i < itemCount; i++) + { + if (prevRow != rows[i]) + { + bounds.x = initBoundsX; + bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING)); + prevRow = rows[i]; + } + + if (i == (*active)) + { + toggle = true; + GuiToggle(bounds, items[i], &toggle); + } + else + { + toggle = false; + GuiToggle(bounds, items[i], &toggle); + if (toggle) *active = i; + } + + bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING)); + } + + return result; +} + +// Toggle Slider control extended +int GuiToggleSlider(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + //bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle slider = { + 0, // Calculated later depending on the active toggle + bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount, + bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + (*active)++; + result = 1; + } + else state = STATE_FOCUSED; + } + + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; + } + + if (*active >= itemCount) *active = 0; + slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))), + GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL))); + + // Draw internal slider + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + + // Draw text in slider + if (text != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = slider.x + slider.width/2 - textBounds.width/2; + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha)); + } + //-------------------------------------------------------------------- + + return result; +} + +// Check Box control, returns 1 when state changed +int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (checked == NULL) checked = &temp; + + 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(CHECKBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + Rectangle totalBounds = { + (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x, + bounds.y, + bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING), + bounds.height, + }; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, totalBounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + *checked = !(*checked); + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK); + + if (*checked) + { + Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)), + bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) }; + GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3))); + } + + GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Combo Box control +int GuiComboBox(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING)); + + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height }; + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + if (*active < 0) *active = 0; + else if (*active > (itemCount - 1)) *active = itemCount - 1; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds) || + CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + *active += 1; + if (*active >= itemCount) *active = 0; // Cyclic combobox + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw combo box main + GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3)))); + GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3)))); + + // Draw selector using a custom button + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount)); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + return result; +} + +// Dropdown Box control +// NOTE: Returns mouse click +int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode) +{ + 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) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (editMode) + { + state = STATE_PRESSED; + + // Check if mouse has been pressed or released outside limits + if (!CheckCollisionPointRec(mousePoint, boundsOpen)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + + // Check if already selected item has been pressed again + if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + + // Check focused and selected item + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + 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)) + { + itemFocused = i; + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + itemSelected = i; + result = 1; // Item selected + } + break; + } + } + + itemBounds = bounds; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + result = 1; + state = STATE_PRESSED; + } + else state = STATE_FOCUSED; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (editMode) GuiPanel(boundsOpen, NULL); + + GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3))); + GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3))); + + if (editMode) + { + // Draw visible items + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + 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) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED))); + } + else if (i == itemFocused) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED))); + } + else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL))); + } + } + + 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)))); +#else + 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; + + // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item... + return result; // Mouse click: result = 1 +} + +// Text Box control +// NOTE: Returns true on ENTER pressed (useful for data validation) +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 + #endif + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement + #endif + + int result = 0; + GuiState state = guiState; + + bool multiline = false; // TODO: Consider multiline text input + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); + + Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); + 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 + // NOTE: Position X value should be updated + Rectangle cursor = { + textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING), + textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), + 2, + (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2 + }; + + if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH); + + // Mouse cursor rectangle + // NOTE: Initialized outside of screen + Rectangle mouseCursor = cursor; + mouseCursor.x = -1; + mouseCursor.width = 1; + + // Auto-cursor movement logic + // NOTE: Cursor moves automatically when key down after some time + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCooldownCounter++; + else + { + autoCursorCooldownCounter = 0; // GLOBAL: Cursor cooldown counter + autoCursorDelayCounter = 0; // GLOBAL: Cursor delay counter + } + + // Blink-cursor frame counter + //if (!autoCursorMode) blinkCursorFrameCounter++; + //else blinkCursorFrameCounter = 0; + + // Update control + //-------------------------------------------------------------------- + // WARNING: Text editing is only supported under certain conditions: + if ((state != STATE_DISABLED) && // Control not disabled + !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode + !guiLocked && // Gui not locked + !guiControlExclusiveMode && // No gui slider on dragging + (wrapMode == TEXT_WRAP_NONE)) // No wrap mode + { + Vector2 mousePosition = GetMousePosition(); + + if (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) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textIndexOffset, &nextCodepointSize); + + textIndexOffset += nextCodepointSize; + + textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex); + } + + int codepoint = GetCharPressed(); // Get Unicode codepoint + if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; + + // 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) < textSize)) + { + // Move forward data from cursor position + for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; + + // Add new codepoint in current cursor position + for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i]; + + textBoxCursorIndex += codepointSize; + textLength += codepointSize; + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + + // Move cursor to start + if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0; + + // Move cursor to end + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength; + + // Delete codepoint from text, after current cursor position + if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_DELETE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + // Move backward text from cursor position + 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'; + } + } + + // Delete related codepoints from text, before current cursor position + if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int i = textBoxCursorIndex - 1; + int accCodepointSize = 0; + + // Move cursor to the end of word if on space already + while ((i > 0) && isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move cursor to the start of the word + while ((i > 0) && !isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move forward text from cursor position + for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize]; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + textBoxCursorIndex -= accCodepointSize; + textLength -= accCodepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int prevCodepointSize = 0; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move backward text from cursor position + for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + + textBoxCursorIndex -= codepointSize; + textLength -= codepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + } + + // Move cursor position with keys + if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int prevCodepointSize = 0; + if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize; + } + } + else if (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_RIGHT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + if ((textBoxCursorIndex + nextCodepointSize) <= textLength) textBoxCursorIndex += nextCodepointSize; + } + } + + // Move cursor position with mouse + if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text + { + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; + int codepointIndex = 0; + float glyphWidth = 0.0f; + float widthToMouseX = 0; + int mouseCursorIndex = 0; + + for (int i = textIndexOffset; i < textLength; i++) + { + codepoint = GetCodepointNext(&text[i], &codepointSize); + codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2))) + { + mouseCursor.x = textBounds.x + widthToMouseX; + mouseCursorIndex = i; + break; + } + + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + + // Check if mouse cursor is at the last position + int textEndWidth = GetTextWidth(text + textIndexOffset); + if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) + { + mouseCursor.x = textBounds.x + textEndWidth; + mouseCursorIndex = textLength; + } + + // Place cursor at required index on mouse click + if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + cursor.x = mouseCursor.x; + textBoxCursorIndex = mouseCursorIndex; + } + } + else mouseCursor.x = -1; + + // Recalculate cursor position.y depending on textBoxCursorIndex + cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING); + //if (multiline) cursor.y = GetTextLines() + + // Finish text editing on ENTER or mouse click outside bounds + if ((!multiline && IsKeyPressed(KEY_ENTER)) || + (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index + result = 1; + } + } + else + { + if (CheckCollisionPointRec(mousePosition, bounds)) + { + state = STATE_FOCUSED; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text + result = 1; + } + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_PRESSED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); + } + else if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED))); + } + else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK); + + // Draw text considering index offset if required + // NOTE: Text index offset depends on cursor position + GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY)) + { + //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0)) + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + + // Draw mouse position cursor (if required) + if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + } + else if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; // Mouse button pressed: result = 1 +} + +/* +// 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 textSize, bool editMode) +{ + bool pressed = false; + + GuiSetStyle(TEXTBOX, TEXT_READONLY, 1); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); + + // TODO: Implement methods to calculate cursor position properly + pressed = GuiTextBox(bounds, text, textSize, editMode); + + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); + GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); + + return pressed; +} +*/ + +// Spinner control, returns selected value +int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + int result = 1; + GuiState state = guiState; + + int tempValue = *value; + + Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING), bounds.y, + bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height }; + + 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(SPINNER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check spinner state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(leftButtonBound, "<")) tempValue--; + if (GuiButton(rightButtonBound, ">")) tempValue++; +#else + if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--; + if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++; +#endif + + if (!editMode) + { + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + result = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode); + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH)); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + *value = tempValue; + return result; +} + +// Value Box control, updates input text with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, 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, "%i", *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)) + { + textValue[keyCount] = (char)key; + keyCount++; + valueHasChanged = true; + } + } + } + + // Delete text + if (keyCount > 0) + { + if (IsKeyPressed(KEY_BACKSPACE)) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToInteger(textValue); + + // NOTE: We are not clamp values until user input finishes + //if (*value > maxValue) *value = maxValue; + //else if (*value < minValue) *value = minValue; + + 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 + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + 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; +} + +// 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; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + 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) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + 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; // 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 - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + else state = STATE_FOCUSED; + } + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + } + + // Control value change check + if (oldValue == *value) result = 0; + else result = 1; + + // 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); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + + // Draw slider internal bar (depends on state) + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED))); + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Slider control extended, returns selected value and has text +int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH)); +} + +// Slider Bar control extended, returns selected value +int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0); +} + +// Progress Bar control extended, shows current progress value +int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + + // Progress bar + Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), + bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0, + bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if (*value > maxValue) *value = maxValue; + + // WARNING: Working with floats could lead to rounding issues + if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue)? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f); + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK); + } + else + { + if (*value > minValue) + { + // Draw progress bar with colored border, more visual + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + } + else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + + if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + 1, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + else + { + // Draw borders not yet reached by value + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y + bounds.height - 1, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + } + + // Draw slider internal progress bar (depends on state) + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Status Bar control +int GuiStatusBar(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Dummy rectangle control, intended for placeholding +int GuiDummyRec(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED))); + //------------------------------------------------------------------ + + return result; +} + +// List View control +int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active) +{ + int result = 0; + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL); + + return result; +} + +// List View control with extended parameters +int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) +{ + int result = 0; + GuiState state = guiState; + + int itemFocused = (focus == NULL)? -1 : *focus; + int itemSelected = (active == NULL)? -1 : *active; + + // Check if we need a scroll bar + bool useScrollBar = false; + if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true; + + // Define base item rectangle [0] + Rectangle itemBounds = { 0 }; + itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING); + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); + if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); + + // Get items on the list + int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + if (visibleItems > count) visibleItems = count; + + int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; + if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; + int endIndex = startIndex + visibleItems; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check mouse inside list view + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Check focused and selected item + for (int i = 0; i < visibleItems; i++) + { + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = startIndex + i; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (itemSelected == (startIndex + i)) itemSelected = -1; + else itemSelected = startIndex + i; + } + break; + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + int wheelMove = (int)GetMouseWheelMove(); + startIndex -= wheelMove; + + if (startIndex < 0) startIndex = 0; + else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; + + endIndex = startIndex + visibleItems; + if (endIndex > count) endIndex = count; + } + } + else itemFocused = -1; + + // Reset item rectangle y to [0] + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // 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))); + + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED))); + } + else + { + if (((startIndex + i) == itemSelected) && (active != NULL)) + { + // Draw item selected + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED))); + } + else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned! + { + // Draw item focused + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED))); + } + else + { + // Draw item normal + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL))); + } + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + Rectangle scrollBarBounds = { + bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Calculate percentage of visible items and apply same percentage to scrollbar + float percentVisible = (float)(endIndex - startIndex)/count; + float sliderSize = bounds.height*percentVisible; + + int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size + int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed + + startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); + + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default + } + //-------------------------------------------------------------------- + + if (active != NULL) *active = itemSelected; + if (focus != NULL) *focus = itemFocused; + if (scrollIndex != NULL) *scrollIndex = startIndex; + + return result; +} + +// Color Panel control - Color (RGBA) variant. +int GuiColorPanel(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + 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. + + GuiColorPanelHSV(bounds, text, &hsv); + + // 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) + { + 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), + color->a }; + } + return result; +} + +// Color Bar Alpha control +// NOTE: Returns alpha value normalized [0..1] +int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +{ + #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE) + #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10 + #endif + + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + 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; + if (*alpha >= 1.0f) *alpha = 1.0f; + //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + + // Draw alpha bar: checked background + if (state != STATE_DISABLED) + { + int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE }; + GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f)); + } + } + + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw alpha bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Bar Hue control +// Returns hue value normalized [0..1] +// NOTE: Other similar bars (for reference): +// Color GuiColorBarSat() [WHITE->color] +// Color GuiColorBarValue() [BLACK->color], HSV/HSL +// float GuiColorBarLuminance() [BLACK->WHITE] +int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) +{ + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + 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; + if (*hue >= 359.0f) *hue = 359.0f; + + } + else state = STATE_FOCUSED; + + /*if (IsKeyDown(KEY_UP)) + { + hue -= 2.0f; + if (hue <= 0.0f) hue = 0.0f; + } + else if (IsKeyDown(KEY_DOWN)) + { + hue += 2.0f; + if (hue >= 360.0f) hue = 360.0f; + }*/ + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + // Draw hue bar:color bars + // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw hue bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Picker control +// NOTE: It's divided in multiple controls: +// Color GuiColorPanel(Rectangle bounds, Color color) +// 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; + + Color temp = { 200, 0, 0, 255 }; + if (color == NULL) color = &temp; + + GuiColorPanel(bounds, NULL, 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); + + //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); + Vector3 rgb = ConvertHSVtoRGB(hsv); + + *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a }; + + return result; +} + +// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering. +// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB. +// NOTE: It's divided in multiple controls: +// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanelHSV() size +int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + + Vector3 tempHsv = { 0 }; + + if (colorHsv == NULL) + { + const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f }; + tempHsv = ConvertRGBtoHSV(tempColor); + colorHsv = &tempHsv; + } + + GuiColorPanelHSV(bounds, NULL, colorHsv); + + const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + + GuiColorBarHue(boundsHue, NULL, &colorHsv->x); + + return result; +} + +// Color Panel control - HSV variant +int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + GuiState state = guiState; + Vector2 pickerSelector = { 0 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; + + pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation + pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value + + Vector3 maxHue = { colorHsv->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) + { + Vector2 mousePoint = GetMousePosition(); + + 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 + 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 state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // 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; +} + +// Message Box control +int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons) +{ + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT) + #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING) + #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12 + #endif + + int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + //int textWidth = GetTextWidth(message) + 2; + + Rectangle textBounds = { 0 }; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + 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 + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + + prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); + //-------------------------------------------------------------------- + + return result; +} + +// Text Input Box control, ask for text +int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive) +{ + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING) + #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_HEIGHT 26 + #endif + + // Used to enable text edit mode + // WARNING: No more than one GuiTextInputBox() should be open at the same time + static bool textEditMode = false; + + int result = -1; + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT; + + int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + + Rectangle textBounds = { 0 }; + if (message != NULL) + { + int textSize = GetTextWidth(message) + 2; + + textBounds.x = bounds.x + bounds.width/2 - textSize/2; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + textBounds.width = (float)textSize; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + } + + Rectangle textBoxBounds = { 0 }; + textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2; + if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4); + textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2; + textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + // Draw message if available + if (message != NULL) + { + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + } + + if (secretViewActive != NULL) + { + static char stars[] = "****************"; + if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height }, + ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode; + + GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive); + } + else + { + if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode; + } + + int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + if (result >= 0) textEditMode = false; + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment); + //-------------------------------------------------------------------- + + return result; // Result is the pressed button index +} + +// Grid control +// NOTE: Returns grid mouse-hover selected cell +// About drawing lines at subpixel spacing, simple put, not easy solution: +// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster +int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell) +{ + // Grid lines alpha amount + #if !defined(RAYGUI_GRID_ALPHA) + #define RAYGUI_GRID_ALPHA 0.15f + #endif + + int result = 0; + GuiState state = guiState; + + Vector2 mousePoint = GetMousePosition(); + Vector2 currentMouseCell = { -1, -1 }; + + float spaceWidth = spacing/(float)subdivs; + int linesV = (int)(bounds.width/spaceWidth) + 1; + int linesH = (int)(bounds.height/spaceWidth) + 1; + + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + // NOTE: Cell values must be the upper left of the cell the mouse is in + currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing); + currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing); + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) + { + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) + { + 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, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + } + + if (mouseCell != NULL) *mouseCell = currentMouseCell; + return result; +} + +//---------------------------------------------------------------------------------- +// Tooltip management functions +// NOTE: Tooltips requires some global variables: tooltipPtr +//---------------------------------------------------------------------------------- +// Enable gui tooltips (global state) +void GuiEnableTooltip(void) { guiTooltip = true; } + +// Disable gui tooltips (global state) +void GuiDisableTooltip(void) { guiTooltip = false; } + +// Set tooltip string +void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } + +//---------------------------------------------------------------------------------- +// Styles loading functions +//---------------------------------------------------------------------------------- + +// Load raygui style file (.rgs) +// NOTE: By default a binary file is expected, that file could contain a custom font, +// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE) +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"); + + if (rgsFile != NULL) + { + char buffer[MAX_LINE_BUFFER_SIZE] = { 0 }; + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + unsigned int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + // Style property: p + + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + GuiSetStyle(controlId, propertyId, (int)propertyValue); + + } break; + case 'f': + { + // Style font: f + + int fontSize = 0; + char charmapFileName[256] = { 0 }; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName); + + Font font = { 0 }; + int *codepoints = NULL; + int codepointCount = 0; + + if (charmapFileName[0] != '0') + { + // Load text data from file + // NOTE: Expected an UTF-8 array of codepoints, no separation + char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName)); + codepoints = LoadCodepoints(textData, &codepointCount); + UnloadFileText(textData); + } + + if (fontFileName[0] != '\0') + { + // In case a font is already loaded and it is not default internal font, unload it + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + + if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount); + else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints + } + + // If font texture not properly loaded, revert to default font and size/spacing + if (font.texture.id == 0) + { + font = GetFontDefault(); + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); + } + + UnloadCodepoints(codepoints); + + if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font); + + } break; + default: break; + } + + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile != NULL) + { + fseek(rgsFile, 0, SEEK_END); + int fileDataSize = ftell(rgsFile); + fseek(rgsFile, 0, SEEK_SET); + + if (fileDataSize > 0) + { + unsigned char *fileData = (unsigned char *)RAYGUI_MALLOC(fileDataSize*sizeof(unsigned char)); + fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile); + + GuiLoadStyleFromMemory(fileData, fileDataSize); + + RAYGUI_FREE(fileData); + } + + fclose(rgsFile); + } + } +} + +// Load style default over global style +void GuiLoadStyleDefault(void) +{ + // We set this variable first to avoid cyclic function calls + // when calling GuiSetStyle() and GuiGetStyle() + guiStyleLoaded = true; + + // Initialize default LIGHT style property values + // WARNING: Default value are applied to all controls on set but + // they can be overwritten later on for every custom control + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff); + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff); + GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff); + GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff); + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff); + GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff); + GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff); + GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff); + GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); + GuiSetStyle(DEFAULT, TEXT_PADDING, 0); + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + // Initialize default extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds + + // Initialize control-specific property values + // NOTE: Those properties are in default list but require specific values by control type + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(SLIDER, TEXT_PADDING, 4); + GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT); + GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0); + GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiSetStyle(TEXTBOX, TEXT_PADDING, 4); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(VALUEBOX, TEXT_PADDING, 0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(SPINNER, TEXT_PADDING, 0); + GuiSetStyle(SPINNER, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(STATUSBAR, TEXT_PADDING, 8); + GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + // Initialize extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(TOGGLE, GROUP_PADDING, 2); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 16); + GuiSetStyle(SLIDER, SLIDER_PADDING, 1); + GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1); + GuiSetStyle(CHECKBOX, CHECK_PADDING, 1); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2); + GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16); + GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2); + GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24); + GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12); + GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28); + GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); + GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8); + GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16); + GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2); + + if (guiFont.texture.id != GetFontDefault().texture.id) + { + // Unload previous font texture + UnloadTexture(guiFont.texture); + RL_FREE(guiFont.recs); + RL_FREE(guiFont.glyphs); + guiFont.recs = NULL; + guiFont.glyphs = NULL; + + // Setup default raylib font + guiFont = GetFontDefault(); + + // NOTE: Default raylib font character 95 is a white square + Rectangle whiteChar = guiFont.recs[95]; + + // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 }); + } +} + +// Get text with icon id prepended +// NOTE: Useful to add icons by name id (enum) instead of +// a number that can change between ricon versions +const char *GuiIconText(int iconId, const char *text) +{ +#if defined(RAYGUI_NO_ICONS) + return NULL; +#else + static char buffer[1024] = { 0 }; + static char iconBuffer[16] = { 0 }; + + if (text != NULL) + { + memset(buffer, 0, 1024); + sprintf(buffer, "#%03i#", iconId); + + for (int i = 5; i < 1024; i++) + { + buffer[i] = text[i - 5]; + if (text[i - 5] == '\0') break; + } + + return buffer; + } + else + { + sprintf(iconBuffer, "#%03i#", iconId); + + return iconBuffer; + } +#endif +} + +#if !defined(RAYGUI_NO_ICONS) +// Get full icons data pointer +unsigned int *GuiGetIcons(void) { return guiIconsPtr; } + +// Load raygui icons file (.rgi) +// NOTE: In case nameIds are required, they can be requested with loadIconsName, +// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH], +// WARNING: guiIconsName[]][] memory should be manually freed! +char **GuiLoadIcons(const char *fileName, bool loadIconsName) +{ + // Style File Structure (.rgi) + // ------------------------------------------------------ + // Offset | Size | Type | Description + // ------------------------------------------------------ + // 0 | 4 | char | Signature: "rGI " + // 4 | 2 | short | Version: 100 + // 6 | 2 | short | reserved + + // 8 | 2 | short | Num icons (N) + // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S) + + // Icons name id (32 bytes per name id) + // foreach (icon) + // { + // 12+32*i | 32 | char | Icon NameId + // } + + // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size) + // S*S pixels/32bit per unsigned int = K unsigned int per icon + // foreach (icon) + // { + // ... | K | unsigned int | Icon Data + // } + + FILE *rgiFile = fopen(fileName, "rb"); + + char **guiIconsName = NULL; + + if (rgiFile != NULL) + { + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + fread(signature, 1, 4, rgiFile); + fread(&version, sizeof(short), 1, rgiFile); + fread(&reserved, sizeof(short), 1, rgiFile); + fread(&iconCount, sizeof(short), 1, rgiFile); + fread(&iconSize, sizeof(short), 1, rgiFile); + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH); + fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile); + } + } + else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR); + + // Read icons data directly over internal icons array + fread(guiIconsPtr, sizeof(unsigned int), iconCount*(iconSize*iconSize/32), rgiFile); + } + + fclose(rgiFile); + } + + return guiIconsName; +} + +// Draw selected icon using rectangles pixel-by-pixel +void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color) +{ + #define BIT_CHECK(a,b) ((a) & (1u<<(b))) + + for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++) + { + for (int k = 0; k < 32; k++) + { + if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k)) + { + #if !defined(RAYGUI_STANDALONE) + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color); + #endif + } + + if ((k == 15) || (k == 31)) y++; + } + } +} + +// Set icon drawing size +void GuiSetIconScale(int scale) +{ + if (scale >= 1) guiIconScale = scale; +} + +#endif // !RAYGUI_NO_ICONS + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- + +// Load style from memory +// WARNING: Binary files only +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + int propertyCount = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'S') && + (signature[3] == ' ')) + { + short controlId = 0; + short propertyId = 0; + unsigned int propertyValue = 0; + + for (int i = 0; i < propertyCount; i++) + { + memcpy(&controlId, fileDataPtr, sizeof(short)); + memcpy(&propertyId, fileDataPtr + 2, sizeof(short)); + memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int)); + fileDataPtr += 8; + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); + } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); + } + + // Font loading is highly dependant on raylib API to load font data and image + +#if !defined(RAYGUI_STANDALONE) + // Load custom font if available + int fontDataSize = 0; + memcpy(&fontDataSize, fileDataPtr, sizeof(int)); + fileDataPtr += 4; + + if (fontDataSize > 0) + { + Font font = { 0 }; + int fontType = 0; // 0-Normal, 1-SDF + + memcpy(&font.baseSize, fileDataPtr, sizeof(int)); + memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int)); + memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + // Load font white rectangle + Rectangle fontWhiteRec = { 0 }; + memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle)); + fileDataPtr += 16; + + // Load font image parameters + int fontImageUncompSize = 0; + int fontImageCompSize = 0; + memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int)); + memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int)); + fileDataPtr += 8; + + Image imFont = { 0 }; + imFont.mipmaps = 1; + memcpy(&imFont.width, fileDataPtr, sizeof(int)); + memcpy(&imFont.height, fileDataPtr + 4, sizeof(int)); + memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize)) + { + // Compressed font atlas image data (DEFLATE), it requires DecompressData() + int dataUncompSize = 0; + unsigned char *compData = (unsigned char *)RAYGUI_MALLOC(fontImageCompSize); + memcpy(compData, fileDataPtr, fontImageCompSize); + fileDataPtr += fontImageCompSize; + + imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize); + + // Security check, dataUncompSize must match the provided fontImageUncompSize + if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted"); + + RAYGUI_FREE(compData); + } + else + { + // Font atlas image data is not compressed + imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageUncompSize); + memcpy(imFont.data, fileDataPtr, fontImageUncompSize); + fileDataPtr += fontImageUncompSize; + } + + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + font.texture = LoadTextureFromImage(imFont); + + RAYGUI_FREE(imFont.data); + + // Validate font atlas texture was loaded correctly + if (font.texture.id != 0) + { + // Load font recs data + int recsDataSize = font.glyphCount*sizeof(Rectangle); + int recsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed recs data + memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize)) + { + // Recs data is compressed, uncompress it + unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_MALLOC(recsDataCompressedSize); + + memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize); + fileDataPtr += recsDataCompressedSize; + + int recsDataUncompSize = 0; + font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted"); + + RAYGUI_FREE(recsDataCompressed); + } + else + { + // Recs data is uncompressed + font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle)); + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle)); + fileDataPtr += sizeof(Rectangle); + } + } + + // Load font glyphs info data + int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph + int glyphsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed glyphs data + memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + // Allocate required glyphs space to fill with data + font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo)); + + if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize)) + { + // Glyphs data is compressed, uncompress it + unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_MALLOC(glyphsDataCompressedSize); + + memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize); + fileDataPtr += glyphsDataCompressedSize; + + int glyphsDataUncompSize = 0; + unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted"); + + unsigned char *glyphsDataUncompPtr = glyphsDataUncomp; + + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int)); + glyphsDataUncompPtr += 16; + } + + RAYGUI_FREE(glypsDataCompressed); + RAYGUI_FREE(glyphsDataUncomp); + } + else + { + // Glyphs data is uncompressed + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int)); + fileDataPtr += 16; + } + } + } + else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture + + GuiSetFont(font); + + // Set font texture source rectangle to be used as white texture to draw shapes + // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call + if ((fontWhiteRec.x > 0) && + (fontWhiteRec.y > 0) && + (fontWhiteRec.width > 0) && + (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec); + } +#endif + } +} + +// Gui get text width considering icon +static int GetTextWidth(const char *text) +{ + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + Vector2 textSize = { 0 }; + int textIconOffset = 0; + + if ((text != NULL) && (text[0] != '\0')) + { + if (text[0] == '#') + { + for (int i = 1; (i < 5) && (text[i] != '\0'); i++) + { + if (text[i] == '#') + { + textIconOffset = i; + break; + } + } + } + + text += textIconOffset; + + // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly + float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + + // Custom MeasureText() implementation + if ((guiFont.texture.id > 0) && (text != NULL)) + { + // Get size in bytes of text, considering end of line and line break + int size = 0; + for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++) + { + if ((text[i] != '\0') && (text[i] != '\n')) size++; + else break; + } + + float scaleFactor = fontSize/(float)guiFont.baseSize; + textSize.y = (float)guiFont.baseSize*scaleFactor; + float glyphWidth = 0.0f; + + for (int i = 0, codepointSize = 0; i < size; i += codepointSize) + { + int codepoint = GetCodepointNext(&text[i], &codepointSize); + int codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); + } + + return (int)textSize.x; +} + +// Get text bounds considering control bounds +static Rectangle GetTextBounds(int control, Rectangle bounds) +{ + Rectangle textBounds = bounds; + + textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); + textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING); + textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); + textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line! + + // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds + switch (control) + { + case COMBOBOX: + case DROPDOWNBOX: + case LISTVIEW: + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW + case SLIDER: + case CHECKBOX: + case VALUEBOX: + case SPINNER: + // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER + default: + { + // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText() + if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING); + else textBounds.x += GuiGetStyle(control, TEXT_PADDING); + } + break; + } + + return textBounds; +} + +// Get text icon if provided and move text cursor +// NOTE: We support up to 999 values for iconId +static const char *GetTextIcon(const char *text, int *iconId) +{ +#if !defined(RAYGUI_NO_ICONS) + *iconId = -1; + if (text[0] == '#') // Maybe we have an icon! + { + char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0' + + int pos = 1; + while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9')) + { + iconValue[pos - 1] = text[pos]; + pos++; + } + + if (text[pos] == '#') + { + *iconId = TextToInteger(iconValue); + + // Move text pointer after icon + // WARNING: If only icon provided, it could point to EOL character: '\0' + if (*iconId >= 0) text += (pos + 1); + } + } +#endif + + return text; +} + +// Get text divided into lines (by line-breaks '\n') +const char **GetTextLines(const char *text, int *count) +{ + #define RAYGUI_MAX_TEXT_LINES 128 + + static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; + for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings + + int textSize = (int)strlen(text); + + lines[0] = text; + int len = 0; + *count = 1; + //int lineSize = 0; // Stores current line size, not returned + + for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++) + { + if (text[i] == '\n') + { + //lineSize = len; + k++; + lines[k] = &text[i + 1]; // WARNING: next value is valid? + len = 0; + *count += 1; + } + else len++; + } + + //lines[*count - 1].size = len; + + return lines; +} + +// Get text width to next space for provided string +static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex) +{ + float width = 0; + int codepointByteCount = 0; + int codepoint = 0; + int index = 0; + float glyphWidth = 0; + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + for (int i = 0; text[i] != '\0'; i++) + { + if (text[i] != ' ') + { + codepoint = GetCodepoint(&text[i], &codepointByteCount); + index = GetGlyphIndex(guiFont, codepoint); + glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor; + width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + else + { + *nextSpaceIndex = i; + break; + } + } + + return width; +} + +// Gui draw text using default font +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint) +{ + #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect + + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + if ((text == NULL) || (text[0] == '\0')) return; // Security check + + // PROCEDURE: + // - Text is processed line per line + // - For every line, horizontal alignment is defined + // - For all text, vertical alignment is defined (multiline text only) + // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only) + + // Get text lines (using '\n' as delimiter) to be processed individually + // WARNING: We can't use GuiTextSplit() function because it can be already used + // before the GuiDrawText() call and its buffer is static, it would be overriden :( + int lineCount = 0; + const char **lines = GetTextLines(text, &lineCount); + + // Text style variables + //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); + int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL); + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing + + // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap + float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2); + float posOffsetY = 0.0f; + + for (int i = 0; i < lineCount; i++) + { + int iconId = 0; + lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor + + // 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? + int textSizeX = GetTextWidth(lines[i]); + + // If text requires an icon, add size to measure + if (iconId >= 0) + { + textSizeX += RAYGUI_ICON_SIZE*guiIconScale; + + // WARNING: If only icon provided, text could be pointing to EOF character: '\0' +#if !defined(RAYGUI_NO_ICONS) + if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING; +#endif + } + + // Check guiTextAlign global variables + switch (alignment) + { + case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break; + case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break; + case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break; + 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; + case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break; + case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + default: break; + } + + // NOTE: Make sure we get pixel-perfect coordinates, + // In case of decimals we got weird text positioning + textBoundsPosition.x = (float)((int)textBoundsPosition.x); + textBoundsPosition.y = (float)((int)textBoundsPosition.y); + //--------------------------------------------------------------------------------- + + // Draw text (with icon if available) + //--------------------------------------------------------------------------------- +#if !defined(RAYGUI_NO_ICONS) + if (iconId >= 0) + { + // 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 += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + } +#endif + // Get size in bytes of text, + // considering end of line and line break + int lineSize = 0; + 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); + int index = GetGlyphIndex(guiFont, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size + + // 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) + { + // Jump to next line if current character reach end of the box limits + 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); + + 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); + } + } + + if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint + else + { + // TODO: There are multiple types of spaces in Unicode, + // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html + if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph + { + if (wrapMode == TEXT_WRAP_NONE) + { + // Draw only required text glyphs fitting the textBounds.width + 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)); + } + } + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + { + // Draw only glyphs inside the bounds + if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + + if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + //--------------------------------------------------------------------------------- + } + +#if defined(RAYGUI_DEBUG_TEXT_BOUNDS) + GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f)); +#endif +} + +// Gui draw rectangle using default raygui plain style with borders +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color) +{ + if (color.a > 0) + { + // Draw rectangle filled with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha)); + } + + if (borderWidth > 0) + { + // Draw rectangle border lines with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + } + +#if defined(RAYGUI_DEBUG_RECS_BOUNDS) + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f)); +#endif +} + +// Draw tooltip using control bounds +static void GuiTooltip(Rectangle controlRec) +{ + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) + { + Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + + if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width); + + GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, NULL); + + int textPadding = GuiGetStyle(LABEL, TEXT_PADDING); + int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_PADDING, 0); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, guiTooltipPtr); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment); + GuiSetStyle(LABEL, TEXT_PADDING, textPadding); + } +} + +// Split controls text into multiple strings +// Also check for multiple columns (required by GuiToggleGroup()) +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + // NOTE: Those definitions could be externally provided if required + + // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user + // textRow is an externally provided array of integers that stores row number for every splitted string + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 1; + + if (textRow != NULL) textRow[0] = 0; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if ((buffer[i] == delimiter) || (buffer[i] == '\n')) + { + result[counter] = buffer + i + 1; + + if (textRow != NULL) + { + if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1; + else textRow[counter] = textRow[counter - 1]; + } + + buffer[i] = '\0'; // Set an end of string at this point + + counter++; + if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + + *count = counter; + + return result; +} + +// Convert color data from RGB to HSV +// NOTE: Color data should be passed normalized +static Vector3 ConvertRGBtoHSV(Vector3 rgb) +{ + Vector3 hsv = { 0 }; + float min = 0.0f; + float max = 0.0f; + float delta = 0.0f; + + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; + + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; + + hsv.z = max; // Value + delta = max - min; + + if (delta < 0.00001f) + { + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + if (max > 0.0f) + { + // NOTE: If max is 0, this divide would cause a crash + hsv.y = (delta/max); // Saturation + } + else + { + // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + // NOTE: Comparing float values could not work properly + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + else + { + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + } + + hsv.x *= 60.0f; // Convert to degrees + + if (hsv.x < 0.0f) hsv.x += 360.0f; + + return hsv; +} + +// Convert color data from HSV to RGB +// NOTE: Color data should be passed normalized +static Vector3 ConvertHSVtoRGB(Vector3 hsv) +{ + Vector3 rgb = { 0 }; + float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f; + long i = 0; + + // NOTE: Comparing float values could not work properly + if (hsv.y <= 0.0f) + { + rgb.x = hsv.z; + rgb.y = hsv.z; + rgb.z = hsv.z; + return rgb; + } + + hh = hsv.x; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + + i = (long)hh; + ff = hh - i; + p = hsv.z*(1.0f - hsv.y); + q = hsv.z*(1.0f - (hsv.y*ff)); + t = hsv.z*(1.0f - (hsv.y*(1.0f - ff))); + + switch (i) + { + case 0: + { + rgb.x = hsv.z; + rgb.y = t; + rgb.z = p; + } break; + case 1: + { + rgb.x = q; + rgb.y = hsv.z; + rgb.z = p; + } break; + case 2: + { + rgb.x = p; + rgb.y = hsv.z; + rgb.z = t; + } break; + case 3: + { + rgb.x = p; + rgb.y = q; + rgb.z = hsv.z; + } break; + case 4: + { + rgb.x = t; + rgb.y = p; + rgb.z = hsv.z; + } break; + case 5: + default: + { + rgb.x = hsv.z; + rgb.y = p; + rgb.z = q; + } break; + } + + return rgb; +} + +// Scroll bar control (used by GuiScrollPanel()) +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) +{ + GuiState state = guiState; + + // Is the scrollbar horizontal or vertical? + bool isVertical = (bounds.width > bounds.height)? false : true; + + // The size (width or height depending on scrollbar type) of the spinner buttons + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? + (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : + (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + + // Slider bar that moves --[///]----- + Rectangle slider = { 0 }; + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = 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){ + (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)spinnerSize, (float)spinnerSize }; + + if (isVertical) + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)), + bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), + (float)sliderSize }; + } + else // horizontal + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)), + bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + (float)sliderSize, + bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) }; + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + 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, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Handle mouse wheel + int wheel = (int)GetMouseWheelMove(); + if (wheel != 0) value += wheel; + + // Handle mouse button down + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + 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); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (!CheckCollisionPointRec(mousePoint, slider)) + { + // If click on scrollbar position but not on slider, place slider directly on that position + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + + state = STATE_PRESSED; + } + + // Keyboard control on mouse hover scrollbar + /* + if (isVertical) + { + if (IsKeyDown(KEY_DOWN)) value += 5; + else if (IsKeyDown(KEY_UP)) value -= 5; + } + else + { + if (IsKeyDown(KEY_RIGHT)) value += 5; + else if (IsKeyDown(KEY_LEFT)) value -= 5; + } + */ + } + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background + + GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background + GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar + + // Draw arrows (using icon if available) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) + { +#if defined(RAYGUI_NO_ICONS) + GuiDrawText(isVertical? "^" : "<", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText(isVertical? "v" : ">", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(isVertical? "#121#" : "#118#", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL + GuiDrawText(isVertical? "#120#" : "#119#", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL +#endif + } + //-------------------------------------------------------------------- + + return value; +} + +// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f +// WARNING: It multiplies current alpha by alpha scale factor +static Color GuiFade(Color color, float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) }; + + return result; +} + +#if defined(RAYGUI_STANDALONE) +// Returns a Color struct from hexadecimal value +static Color GetColor(int hexValue) +{ + Color color; + + color.r = (unsigned char)(hexValue >> 24) & 0xFF; + color.g = (unsigned char)(hexValue >> 16) & 0xFF; + color.b = (unsigned char)(hexValue >> 8) & 0xFF; + color.a = (unsigned char)hexValue & 0xFF; + + return color; +} + +// Returns hexadecimal value for a Color +static int ColorToInt(Color color) +{ + return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a); +} + +// Check if point is inside rectangle +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && + (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Formatting of text with variables to 'embed' +static const char *TextFormat(const char *text, ...) +{ + #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE) + #define RAYGUI_TEXTFORMAT_MAX_SIZE 256 + #endif + + static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE]; + + va_list args; + va_start(args, text); + vsprintf(buffer, text, args); + va_end(args); + + return buffer; +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + +// Split string into multiple strings +const char **TextSplit(const char *text, char delimiter, int *count) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 0; + + if (text != NULL) + { + counter = 1; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if (buffer[i] == delimiter) + { + buffer[i] = '\0'; // Set an end of string at this point + result[counter] = buffer + i + 1; + counter++; + + if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + } + + *count = counter; + return result; +} + +// Get integer value from text +// NOTE: This function replaces atoi() [stdlib.h] +static int TextToInteger(const char *text) +{ + int value = 0; + int sign = 1; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + + for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0'); + + 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) +{ + static char utf8[6] = { 0 }; + int size = 0; + + if (codepoint <= 0x7f) + { + utf8[0] = (char)codepoint; + size = 1; + } + else if (codepoint <= 0x7ff) + { + utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); + utf8[1] = (char)((codepoint & 0x3f) | 0x80); + size = 2; + } + else if (codepoint <= 0xffff) + { + utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); + utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[2] = (char)((codepoint & 0x3f) | 0x80); + size = 3; + } + else if (codepoint <= 0x10ffff) + { + utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0); + utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); + utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[3] = (char)((codepoint & 0x3f) | 0x80); + size = 4; + } + + *byteSize = size; + + return utf8; +} + +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Total number of bytes processed are returned as a parameter +// NOTE: the standard says U+FFFD should be returned in case of errors +// but that character is not supported by the default font in raylib +static int GetCodepointNext(const char *text, int *codepointSize) +{ + const char *ptr = text; + int codepoint = 0x3f; // Codepoint (defaults to '?') + *codepointSize = 1; + + // Get current codepoint and bytes processed + 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 + 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 + 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 + codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); + *codepointSize = 2; + } + else if (0x00 == (0x80 & ptr[0])) + { + // 1 byte UTF-8 codepoint + codepoint = ptr[0]; + *codepointSize = 1; + } + + return codepoint; +} +#endif // RAYGUI_STANDALONE + +#endif // RAYGUI_IMPLEMENTATION diff --git a/projects/VS2022/examples/core_directory_files.vcxproj b/projects/VS2022/examples/core_directory_files.vcxproj index 24dd573f8..426fbfca8 100644 --- a/projects/VS2022/examples/core_directory_files.vcxproj +++ b/projects/VS2022/examples/core_directory_files.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {7467E9AE-844F-444D-8A3F-17397544BA21} Win32Proj core_directory_files 10.0 diff --git a/projects/VS2022/examples/shapes_pie_chart.vcxproj b/projects/VS2022/examples/shapes_pie_chart.vcxproj index 058a9b577..ad1cf93d1 100644 --- a/projects/VS2022/examples/shapes_pie_chart.vcxproj +++ b/projects/VS2022/examples/shapes_pie_chart.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A} Win32Proj shapes_pie_chart 10.0 diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 48f3762dd..d17c569c5 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -371,25 +371,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "ex EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{BB58A5FB-1A35-4471-86D0-A5189EC541B3}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "web", "web", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_pie_chart", "examples\shapes_pie_chart.vcxproj", "{61997220-5383-4AE5-ABD4-5F45AE1B0F2A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_pie_chart", "examples\shapes_pie_chart.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_directory_files", "examples\core_directory_files.vcxproj", "{7467E9AE-844F-444D-8A3F-17397544BA21}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_directory_files", "examples\core_directory_files.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_kaleidoscope", "examples\shapes_kaleidoscope.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_recursive_tree", "examples\shapes_recursive_tree.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_triangle_strip", "examples\shapes_triangle_strip.vcxproj", "{2CCCD9E4-9058-4291-BD89-39C979F0CA1E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_simple_particles", "examples\shapes_simple_particles.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_simple_particles", "examples\shapes_simple_particles.vcxproj", "{497FDF54-9762-4048-A833-61CC3980A0FB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -4413,222 +4399,270 @@ Global {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|ARM64.Build.0 = Debug|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.ActiveCfg = Debug|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x64.Build.0 = Debug|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.ActiveCfg = Debug|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Debug|x86.Build.0 = Debug|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.ActiveCfg = Release|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|ARM64.Build.0 = Release|ARM64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.ActiveCfg = Release|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x64.Build.0 = Release|x64 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.ActiveCfg = Release|Win32 - {9DB1F875-6E65-4195-B23F-ED8095C0B99C}.Release|x86.Build.0 = Release|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|ARM64.Build.0 = Debug|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.ActiveCfg = Debug|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x64.Build.0 = Debug|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.ActiveCfg = Debug|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Debug|x86.Build.0 = Debug|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.ActiveCfg = Release|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|ARM64.Build.0 = Release|ARM64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.ActiveCfg = Release|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x64.Build.0 = Release|x64 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.ActiveCfg = Release|Win32 - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|ARM64.Build.0 = Debug|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.ActiveCfg = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x64.Build.0 = Debug|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.ActiveCfg = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Debug|x86.Build.0 = Debug|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.ActiveCfg = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|ARM64.Build.0 = Release|ARM64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.ActiveCfg = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x64.Build.0 = Release|x64 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.ActiveCfg = Release|Win32 - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|ARM64.Build.0 = Debug|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.ActiveCfg = Debug|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x64.Build.0 = Debug|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.ActiveCfg = Debug|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Debug|x86.Build.0 = Debug|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|ARM64.Build.0 = Release|ARM64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.ActiveCfg = Release|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x64.Build.0 = Release|x64 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.ActiveCfg = Release|Win32 + {8E132D5A-2C00-48D0-8747-97E41356F26F}.Release|x86.Build.0 = Release|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|ARM64.Build.0 = Debug|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.ActiveCfg = Debug|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x64.Build.0 = Debug|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.ActiveCfg = Debug|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Debug|x86.Build.0 = Debug|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.ActiveCfg = Release|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|ARM64.Build.0 = Release|ARM64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.ActiveCfg = Release|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x64.Build.0 = Release|x64 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.ActiveCfg = Release|Win32 + {A4662163-83E7-4309-8CAA-B0BF13655FE6}.Release|x86.Build.0 = Release|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|ARM64.Build.0 = Debug|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.ActiveCfg = Debug|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x64.Build.0 = Debug|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.ActiveCfg = Debug|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Debug|x86.Build.0 = Debug|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.ActiveCfg = Release|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|ARM64.Build.0 = Release|ARM64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.ActiveCfg = Release|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x64.Build.0 = Release|x64 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.ActiveCfg = Release|Win32 + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20}.Release|x86.Build.0 = Release|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|ARM64.Build.0 = Debug|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.ActiveCfg = Debug|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x64.Build.0 = Debug|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.ActiveCfg = Debug|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Debug|x86.Build.0 = Debug|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.ActiveCfg = Release|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|ARM64.Build.0 = Release|ARM64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.ActiveCfg = Release|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x64.Build.0 = Release|x64 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.ActiveCfg = Release|Win32 + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}.Release|x86.Build.0 = Release|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|ARM64.Build.0 = Debug|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.ActiveCfg = Debug|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x64.Build.0 = Debug|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.ActiveCfg = Debug|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Debug|x86.Build.0 = Debug|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.ActiveCfg = Release|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|ARM64.Build.0 = Release|ARM64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.ActiveCfg = Release|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x64.Build.0 = Release|x64 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.ActiveCfg = Release|Win32 + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}.Release|x86.Build.0 = Release|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|ARM64.Build.0 = Debug|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.ActiveCfg = Debug|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x64.Build.0 = Debug|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.ActiveCfg = Debug|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Debug|x86.Build.0 = Debug|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.ActiveCfg = Release|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|ARM64.Build.0 = Release|ARM64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.ActiveCfg = Release|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x64.Build.0 = Release|x64 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.ActiveCfg = Release|Win32 + {0C442799-B09C-4CD1-9538-711B6E85E9BF}.Release|x86.Build.0 = Release|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|ARM64.Build.0 = Debug|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.ActiveCfg = Debug|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x64.Build.0 = Debug|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.ActiveCfg = Debug|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Debug|x86.Build.0 = Debug|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.ActiveCfg = Release|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|ARM64.Build.0 = Release|ARM64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.ActiveCfg = Release|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x64.Build.0 = Release|x64 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.ActiveCfg = Release|Win32 + {DFB40A10-F8B7-412A-BCC3-5EE49294D816}.Release|x86.Build.0 = Release|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|ARM64.Build.0 = Debug|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.ActiveCfg = Debug|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x64.Build.0 = Debug|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.ActiveCfg = Debug|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Debug|x86.Build.0 = Debug|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.ActiveCfg = Release|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|ARM64.Build.0 = Release|ARM64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.ActiveCfg = Release|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x64.Build.0 = Release|x64 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.ActiveCfg = Release|Win32 + {BB58A5FB-1A35-4471-86D0-A5189EC541B3}.Release|x86.Build.0 = Release|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|ARM64.Build.0 = Debug|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|x64.ActiveCfg = Debug|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|x64.Build.0 = Debug|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|x86.ActiveCfg = Debug|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Debug|x86.Build.0 = Debug|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|ARM64.ActiveCfg = Release|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|ARM64.Build.0 = Release|ARM64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|x64.ActiveCfg = Release|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|x64.Build.0 = Release|x64 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|x86.ActiveCfg = Release|Win32 + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A}.Release|x86.Build.0 = Release|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|ARM64.Build.0 = Debug|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|x64.ActiveCfg = Debug|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|x64.Build.0 = Debug|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|x86.ActiveCfg = Debug|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Debug|x86.Build.0 = Debug|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|ARM64.ActiveCfg = Release|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|ARM64.Build.0 = Release|ARM64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|x64.ActiveCfg = Release|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|x64.Build.0 = Release|x64 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|x86.ActiveCfg = Release|Win32 + {7467E9AE-844F-444D-8A3F-17397544BA21}.Release|x86.Build.0 = Release|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|ARM64.Build.0 = Debug|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|x64.ActiveCfg = Debug|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|x64.Build.0 = Debug|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|x86.ActiveCfg = Debug|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Debug|x86.Build.0 = Debug|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|ARM64.ActiveCfg = Release|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|ARM64.Build.0 = Release|ARM64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x64.ActiveCfg = Release|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x64.Build.0 = Release|x64 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x86.ActiveCfg = Release|Win32 + {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4796,7 +4830,7 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} @@ -4808,10 +4842,17 @@ Global {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021} + {A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {278D8859-20B1-428F-8448-064F46E1F021} + {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC} = {E9D708A5-9C1F-4B84-A795-C5F191801762} + {0C442799-B09C-4CD1-9538-711B6E85E9BF} = {278D8859-20B1-428F-8448-064F46E1F021} + {DFB40A10-F8B7-412A-BCC3-5EE49294D816} = {278D8859-20B1-428F-8448-064F46E1F021} + {BB58A5FB-1A35-4471-86D0-A5189EC541B3} = {278D8859-20B1-428F-8448-064F46E1F021} + {61997220-5383-4AE5-ABD4-5F45AE1B0F2A} = {278D8859-20B1-428F-8448-064F46E1F021} + {7467E9AE-844F-444D-8A3F-17397544BA21} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {497FDF54-9762-4048-A833-61CC3980A0FB} = {278D8859-20B1-428F-8448-064F46E1F021} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From 8e052b81b45e33eb33b57d501424221480c6e872 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Oct 2025 19:59:28 +0200 Subject: [PATCH 025/102] REVIEWED: New examples on VS project --- examples/Makefile | 8 +- examples/Makefile.Web | 26 +- examples/README.md | 15 +- examples/core/core_clipboard_text.c | 4 +- examples/examples_list.txt | 5 + examples/shapes/shapes_clock_of_clocks.c | 2 +- examples/shapes/shapes_mouse_trail.c | 2 +- examples/shapes/shapes_pie_chart.c | 6 +- examples/shapes/shapes_recursive_tree.c | 6 +- examples/shapes/shapes_simple_particles.c | 93 ++- examples/shapes/shapes_starfield.c | 4 +- examples/shapes/shapes_triangle_strip.c | 2 +- examples/text/text_words_alignment.c | 6 +- .../examples/core_clipboard_text.vcxproj | 569 ++++++++++++++++++ .../examples/shapes_clock_of_clocks.vcxproj | 569 ++++++++++++++++++ .../examples/shapes_mouse_trail.vcxproj | 569 ++++++++++++++++++ .../VS2022/examples/shapes_starfield.vcxproj | 569 ++++++++++++++++++ .../examples/text_words_alignment.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 143 ++++- tools/rexm/examples_report.md | 7 + 20 files changed, 3098 insertions(+), 76 deletions(-) create mode 100644 projects/VS2022/examples/core_clipboard_text.vcxproj create mode 100644 projects/VS2022/examples/shapes_clock_of_clocks.vcxproj create mode 100644 projects/VS2022/examples/shapes_mouse_trail.vcxproj create mode 100644 projects/VS2022/examples/shapes_starfield.vcxproj create mode 100644 projects/VS2022/examples/text_words_alignment.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 523339d06..eb6725756 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -512,6 +512,7 @@ CORE = \ core/core_automation_events \ core/core_basic_screen_manager \ core/core_basic_window \ + core/core_clipboard_text \ core/core_custom_frame_control \ core/core_custom_logging \ core/core_delta_time \ @@ -546,6 +547,7 @@ SHAPES = \ shapes/shapes_bouncing_ball \ shapes/shapes_bullet_hell \ shapes/shapes_circle_sector_drawing \ + shapes/shapes_clock_of_clocks \ shapes/shapes_collision_area \ shapes/shapes_colors_palette \ shapes/shapes_dashed_line \ @@ -559,12 +561,14 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ + shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ shapes/shapes_starfield \ shapes/shapes_top_down_lights \ @@ -613,8 +617,8 @@ TEXT = \ text/text_sprite_fonts \ text/text_unicode_emojis \ text/text_unicode_ranges \ - text/text_writing_anim \ - text/text_words_alignment + text/text_words_alignment \ + text/text_writing_anim MODELS = \ models/models_animation_gpu_skinning \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index c5e9138f5..e365a5fee 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -512,6 +512,7 @@ CORE = \ core/core_automation_events \ core/core_basic_screen_manager \ core/core_basic_window \ + core/core_clipboard_text \ core/core_custom_frame_control \ core/core_custom_logging \ core/core_delta_time \ @@ -546,6 +547,7 @@ SHAPES = \ shapes/shapes_bouncing_ball \ shapes/shapes_bullet_hell \ shapes/shapes_circle_sector_drawing \ + shapes/shapes_clock_of_clocks \ shapes/shapes_collision_area \ shapes/shapes_colors_palette \ shapes/shapes_dashed_line \ @@ -559,12 +561,14 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ shapes/shapes_rectangle_scaling \ shapes/shapes_recursive_tree \ shapes/shapes_ring_drawing \ shapes/shapes_rounded_rectangle_drawing \ + shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ shapes/shapes_starfield \ shapes/shapes_top_down_lights \ @@ -613,8 +617,8 @@ TEXT = \ text/text_sprite_fonts \ text/text_unicode_emojis \ text/text_unicode_ranges \ - text/text_writing_anim \ - text/text_words_alignment + text/text_words_alignment \ + text/text_writing_anim MODELS = \ models/models_animation_gpu_skinning \ @@ -736,6 +740,9 @@ core/core_basic_screen_manager: core/core_basic_screen_manager.c core/core_basic_window: core/core_basic_window.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_clipboard_text: core/core_clipboard_text.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + core/core_custom_frame_control: core/core_custom_frame_control.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -836,6 +843,9 @@ shapes/shapes_bullet_hell: shapes/shapes_bullet_hell.c shapes/shapes_circle_sector_drawing: shapes/shapes_circle_sector_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_clock_of_clocks: shapes/shapes_clock_of_clocks.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_collision_area: shapes/shapes_collision_area.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -875,6 +885,9 @@ shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_pie_chart: shapes/shapes_pie_chart.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -893,9 +906,15 @@ shapes/shapes_ring_drawing: shapes/shapes_ring_drawing.c shapes/shapes_rounded_rectangle_drawing: shapes/shapes_rounded_rectangle_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_simple_particles: shapes/shapes_simple_particles.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_splines_drawing: shapes/shapes_splines_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_starfield: shapes/shapes_starfield.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_top_down_lights: shapes/shapes_top_down_lights.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -1078,6 +1097,9 @@ text/text_unicode_ranges: text/text_unicode_ranges.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file text/resources/NotoSansTC-Regular.ttf@resources/NotoSansTC-Regular.ttf +text/text_words_alignment: text/text_words_alignment.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + text/text_writing_anim: text/text_writing_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 16e44aa2b..e8b6ba4bf 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 176] +## EXAMPLES COLLECTION [TOTAL: 183] -### category: core [41] +### category: core [42] Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. @@ -66,8 +66,9 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | +| [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | -### category: shapes [27] +### category: shapes [31] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -93,13 +94,17 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_top_down_lights](shapes/shapes_top_down_lights.c) | shapes_top_down_lights | ⭐⭐⭐⭐️ | 4.2 | 4.2 | [Jeffery Myers](https://github.com/JeffM2501) | | [shapes_rectangle_advanced](shapes/shapes_rectangle_advanced.c) | shapes_rectangle_advanced | ⭐⭐⭐⭐️ | 5.5 | 5.5 | [Everton Jr.](https://github.com/evertonse) | | [shapes_splines_drawing](shapes/shapes_splines_drawing.c) | shapes_splines_drawing | ⭐⭐⭐☆ | 5.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | -| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐⭐⭐☆ | 5.5 | 5.5 | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_digital_clock](shapes/shapes_digital_clock.c) | shapes_digital_clock | ⭐⭐⭐⭐️ | 5.5 | 5.6 | [Hamza RAHAL](https://github.com/hmz-rhl) | | [shapes_double_pendulum](shapes/shapes_double_pendulum.c) | shapes_double_pendulum | ⭐⭐☆☆ | 5.5 | 5.5 | [JoeCheong](https://github.com/Joecheong2006) | | [shapes_dashed_line](shapes/shapes_dashed_line.c) | shapes_dashed_line | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) | | [shapes_triangle_strip](shapes/shapes_triangle_strip.c) | shapes_triangle_strip | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | | [shapes_vector_angle](shapes/shapes_vector_angle.c) | shapes_vector_angle | ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | +| [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐☆☆☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | shapes_kaleidoscope | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | +| [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | shapes_clock_of_clocks | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [[Balamurugan R]](https://github.com/[Bala050814]) | +| [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐☆☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | +| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐☆☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: textures [26] @@ -154,7 +159,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat | [text_3d_drawing](text/text_3d_drawing.c) | text_3d_drawing | ⭐⭐⭐⭐️ | 3.5 | 4.0 | [Vlad Adrian](https://github.com/demizdor) | | [text_codepoints_loading](text/text_codepoints_loading.c) | text_codepoints_loading | ⭐⭐⭐☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [text_inline_styling](text/text_inline_styling.c) | text_inline_styling | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | -| [text_words_alignment](text/text_words_alignment.c) | text_words_alignment | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [text_words_alignment](text/text_words_alignment.c) | text_words_alignment | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: models [25] diff --git a/examples/core/core_clipboard_text.c b/examples/core/core_clipboard_text.c index 973163cb5..2be64154b 100644 --- a/examples/core/core_clipboard_text.c +++ b/examples/core/core_clipboard_text.c @@ -4,14 +4,14 @@ * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.6-dev +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * * Example contributed by Robin (@RobinsAviary) 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) 2025-2025 Robin (@RobinsAviary) +* Copyright (c) 2025 Robin (@RobinsAviary) * ********************************************************************************************/ diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 9770975fb..b86a4bc02 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -185,3 +185,8 @@ others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@ar others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal +core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary +shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates +shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] +shapes;shapes_simple_particles;★☆☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant +shapes;shapes_starfield;★☆☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates diff --git a/examples/shapes/shapes_clock_of_clocks.c b/examples/shapes/shapes_clock_of_clocks.c index 0418255e4..493e53b5e 100644 --- a/examples/shapes/shapes_clock_of_clocks.c +++ b/examples/shapes/shapes_clock_of_clocks.c @@ -4,7 +4,7 @@ * * Example complexity rating: [★★☆☆] 2/4 * -* Example originally created with raylib 5.5 +* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev * * Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5) * diff --git a/examples/shapes/shapes_mouse_trail.c b/examples/shapes/shapes_mouse_trail.c index b1cb706f2..88a7c0ce5 100644 --- a/examples/shapes/shapes_mouse_trail.c +++ b/examples/shapes/shapes_mouse_trail.c @@ -31,7 +31,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - Draw a mouse trail"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - mouse trail"); // Array to store the history of mouse positions (our fixed-size queue) Vector2 trailPositions[MAX_TRAIL_LENGTH] = { 0 }; diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c index 68993ed01..35250c5be 100644 --- a/examples/shapes/shapes_pie_chart.c +++ b/examples/shapes/shapes_pie_chart.c @@ -2,9 +2,9 @@ * * raylib [shapes] example - pie chart * -* Example complexity rating: [★★☆☆] 2/4 +* Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* Example originally created with raylib 5.5, last time updated with raylib 5.6 * * Example contributed by Gideon Serfontein (@GideonSerf) and reviewed by Ramon Santamaria (@raysan5) * @@ -32,7 +32,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - interactive pie chart"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - pie chart"); #define MAX_SLICES 10 int sliceCount = 7; diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c index 7ed02e5c2..4d0042419 100644 --- a/examples/shapes/shapes_recursive_tree.c +++ b/examples/shapes/shapes_recursive_tree.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [shapes] example - shapes recursive tree +* raylib [shapes] example - recursive tree * * Example complexity rating: [★★★☆] 3/4 * @@ -11,7 +11,7 @@ * 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) 2018-2025 Jopestpe (@jopestpe) +* Copyright (c) 2025 Jopestpe (@jopestpe) * ********************************************************************************************/ @@ -46,7 +46,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - shapes recursive tree"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - recursive tree"); Vector2 start = { (screenWidth/2.0f) - 125.0f, (float)screenHeight }; float angle = 40.0f; diff --git a/examples/shapes/shapes_simple_particles.c b/examples/shapes/shapes_simple_particles.c index aae85f35d..5bef0917a 100644 --- a/examples/shapes/shapes_simple_particles.c +++ b/examples/shapes/shapes_simple_particles.c @@ -31,16 +31,17 @@ typedef enum ParticleType { FIRE } ParticleType; -static const char particleTypesChar[3][10] = { "WATER", "SMOKE", "FIRE" }; +static const char particleTypeNames[3][10] = { "WATER", "SMOKE", "FIRE" }; typedef struct Particle { + ParticleType type; // Particle type (WATER, SMOKE, FIRE) Vector2 position; // Particle position on screen Vector2 velocity; // Particle current speed and direction - bool alive; // Particle alive: inside screen and life time - float lifeTime; // Particle life time - ParticleType type; // Particle type (WATER, SMOKE, FIRE) float radius; // Particle radius Color color; // Particle color + + float lifeTime; // Particle life time + bool alive; // Particle alive: inside screen and life time } Particle; typedef struct CircularBuffer { @@ -68,7 +69,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - particles"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - simple particles"); // Definition of particles Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array @@ -90,13 +91,11 @@ int main(void) // Emit new particles: when emissionRate is 1, emit every frame if (emissionRate < 0) { - if (rand()%(-emissionRate) == 0) - EmitParticle(&circularBuffer, emitterPosition, currentType); + if (rand()%(-emissionRate) == 0) EmitParticle(&circularBuffer, emitterPosition, currentType); } else { - for (int i = 0; i <= emissionRate; ++i) - EmitParticle(&circularBuffer, emitterPosition, currentType); + for (int i = 0; i <= emissionRate; ++i) EmitParticle(&circularBuffer, emitterPosition, currentType); } // Update the parameters of each particle @@ -105,43 +104,37 @@ int main(void) UpdateCircularBuffer(&circularBuffer); // Change Particle Emission Rate (UP/DOWN arrows) - if (IsKeyPressed(KEY_UP)) - ++emissionRate; - if (IsKeyPressed(KEY_DOWN)) - --emissionRate; + if (IsKeyPressed(KEY_UP)) emissionRate++; + if (IsKeyPressed(KEY_DOWN)) emissionRate--; // Change Particle Type (LEFT/RIGHT arrows) - if (IsKeyPressed(KEY_RIGHT)) - (currentType == FIRE) ? (currentType = WATER) : ++currentType; - if (IsKeyPressed(KEY_LEFT)) - (currentType == WATER) ? (currentType = FIRE) : --currentType; + if (IsKeyPressed(KEY_RIGHT)) (currentType == FIRE)? (currentType = WATER) : currentType++; + if (IsKeyPressed(KEY_LEFT)) (currentType == WATER)? (currentType = FIRE) : currentType--; - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) - emitterPosition = GetMousePosition(); + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) emitterPosition = GetMousePosition(); + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(RAYWHITE); + ClearBackground(RAYWHITE); - // Call the function with a loop to draw all particles - DrawParticles(&circularBuffer); + // Call the function with a loop to draw all particles + DrawParticles(&circularBuffer); - // Draw UI and Instructions - DrawRectangle(5, 5, 315, 75, Fade(SKYBLUE, 0.5f)); - DrawRectangleLines(5, 5, 315, 75, BLUE); + // Draw UI and Instructions + DrawRectangle(5, 5, 315, 75, Fade(SKYBLUE, 0.5f)); + DrawRectangleLines(5, 5, 315, 75, BLUE); - DrawText("CONTROLS:", 15, 15, 10, BLACK); - DrawText("UP/DOWN: Change Particle Emission Rate", 15, 35, 10, BLACK); - DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK); + DrawText("CONTROLS:", 15, 15, 10, BLACK); + DrawText("UP/DOWN: Change Particle Emission Rate", 15, 35, 10, BLACK); + DrawText("LEFT/RIGHT: Change Particle Type (Water, Smoke, Fire)", 15, 55, 10, BLACK); - if (emissionRate < 0) - DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypesChar[currentType]), 15, 95, 10, DARKGRAY); - else - DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypesChar[currentType]), 15, 95, 10, DARKGRAY); + if (emissionRate < 0) DrawText(TextFormat("Particles every %d frames | Type: %s", -emissionRate, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY); + else DrawText(TextFormat("%d Particles per frame | Type: %s", emissionRate + 1, particleTypeNames[currentType]), 15, 95, 10, DARKGRAY); - DrawFPS(screenWidth - 80, 10); + DrawFPS(screenWidth - 80, 10); EndDrawing(); //---------------------------------------------------------------------------------- @@ -163,6 +156,7 @@ int main(void) static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition, ParticleType type) { Particle *newParticle = AddToCircularBuffer(circularBuffer); + // If buffer is full, newParticle is NULL if (newParticle != NULL) { @@ -174,21 +168,25 @@ static void EmitParticle(CircularBuffer *circularBuffer, Vector2 emitterPosition float speed = (float)(rand()%10)/5.0f; switch (type) { - case WATER: - newParticle->radius = 5.0f; - newParticle->color = BLUE; - break; - case SMOKE: - newParticle->radius = 7.0f; - newParticle->color = GRAY; - break; - case FIRE: - newParticle->radius = 10.0f; - newParticle->color = YELLOW; - speed /= 10.0f; - break; - default: break; + case WATER: + { + newParticle->radius = 5.0f; + newParticle->color = BLUE; + } break; + case SMOKE: + { + newParticle->radius = 7.0f; + newParticle->color = GRAY; + } break; + case FIRE: + { + newParticle->radius = 10.0f; + newParticle->color = YELLOW; + speed /= 10.0f; + } break; + default: break; } + float direction = (float)(rand()%360); newParticle->velocity = (Vector2){ speed*cosf(direction*DEG2RAD), speed*sinf(direction*DEG2RAD) }; } @@ -253,6 +251,7 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int circularBuffer->buffer[i].alive = false; } } + static void UpdateCircularBuffer(CircularBuffer *circularBuffer) { // Update circular buffer: advance tail over dead particles diff --git a/examples/shapes/shapes_starfield.c b/examples/shapes/shapes_starfield.c index 457912dec..df543d066 100644 --- a/examples/shapes/shapes_starfield.c +++ b/examples/shapes/shapes_starfield.c @@ -1,10 +1,10 @@ /******************************************************************************************* * -* raylib [shapes] example - simple starfield +* raylib [shapes] example - starfield * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5 +* Example originally created with raylib 5.5, last time updated with raylib 5.6-dev * * Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5) * diff --git a/examples/shapes/shapes_triangle_strip.c b/examples/shapes/shapes_triangle_strip.c index ee4556d25..d8b5faeea 100644 --- a/examples/shapes/shapes_triangle_strip.c +++ b/examples/shapes/shapes_triangle_strip.c @@ -11,7 +11,7 @@ * 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) 2018-2025 Jopestpe (@jopestpe) +* Copyright (c) 2025 Jopestpe (@jopestpe) * ********************************************************************************************/ diff --git a/examples/text/text_words_alignment.c b/examples/text/text_words_alignment.c index 0f012ab75..352b3cd37 100644 --- a/examples/text/text_words_alignment.c +++ b/examples/text/text_words_alignment.c @@ -1,10 +1,10 @@ /******************************************************************************************* * -* raylib [text] example - text alignment +* raylib [text] example - words alignment * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.0, last time updated with raylib 5.5 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * * Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5) * @@ -38,7 +38,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [text] example - text alignment"); + InitWindow(screenWidth, screenHeight, "raylib [text] example - words alignment"); // Define the rectangle we will draw the text in Rectangle textContainerRect = (Rectangle){ screenWidth/2-screenWidth/4, screenHeight/2-screenHeight/3, screenWidth/2, screenHeight*2/3 }; diff --git a/projects/VS2022/examples/core_clipboard_text.vcxproj b/projects/VS2022/examples/core_clipboard_text.vcxproj new file mode 100644 index 000000000..5b0b3e16f --- /dev/null +++ b/projects/VS2022/examples/core_clipboard_text.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {124935CC-73BB-489E-92E8-4F922A85DB5D} + Win32Proj + core_clipboard_text + 10.0 + core_clipboard_text + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/shapes_clock_of_clocks.vcxproj b/projects/VS2022/examples/shapes_clock_of_clocks.vcxproj new file mode 100644 index 000000000..94b1713ec --- /dev/null +++ b/projects/VS2022/examples/shapes_clock_of_clocks.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} + Win32Proj + shapes_clock_of_clocks + 10.0 + shapes_clock_of_clocks + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/shapes_mouse_trail.vcxproj b/projects/VS2022/examples/shapes_mouse_trail.vcxproj new file mode 100644 index 000000000..edc65c027 --- /dev/null +++ b/projects/VS2022/examples/shapes_mouse_trail.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} + Win32Proj + shapes_mouse_trail + 10.0 + shapes_mouse_trail + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/shapes_starfield.vcxproj b/projects/VS2022/examples/shapes_starfield.vcxproj new file mode 100644 index 000000000..5cfc0a6d3 --- /dev/null +++ b/projects/VS2022/examples/shapes_starfield.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} + Win32Proj + shapes_starfield + 10.0 + shapes_starfield + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/text_words_alignment.vcxproj b/projects/VS2022/examples/text_words_alignment.vcxproj new file mode 100644 index 000000000..be9c1614e --- /dev/null +++ b/projects/VS2022/examples/text_words_alignment.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {29B00F47-BE91-4A1F-B87D-B1302F038316} + Win32Proj + text_words_alignment + 10.0 + text_words_alignment + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\text + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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 d17c569c5..5a784adbe 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -377,6 +377,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_directory_files", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_simple_particles", "examples\shapes_simple_particles.vcxproj", "{497FDF54-9762-4048-A833-61CC3980A0FB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "text_words_alignment", "examples\text_words_alignment.vcxproj", "{29B00F47-BE91-4A1F-B87D-B1302F038316}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_clipboard_text", "examples\core_clipboard_text.vcxproj", "{124935CC-73BB-489E-92E8-4F922A85DB5D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_clock_of_clocks", "examples\shapes_clock_of_clocks.vcxproj", "{AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_mouse_trail", "examples\shapes_mouse_trail.vcxproj", "{0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield", "examples\shapes_starfield.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4663,6 +4673,126 @@ Global {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x64.Build.0 = Release|x64 {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x86.ActiveCfg = Release|Win32 {497FDF54-9762-4048-A833-61CC3980A0FB}.Release|x86.Build.0 = Release|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|ARM64.Build.0 = Debug|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|x64.ActiveCfg = Debug|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|x64.Build.0 = Debug|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|x86.ActiveCfg = Debug|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Debug|x86.Build.0 = Debug|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|ARM64.ActiveCfg = Release|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|ARM64.Build.0 = Release|ARM64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|x64.ActiveCfg = Release|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|x64.Build.0 = Release|x64 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|x86.ActiveCfg = Release|Win32 + {29B00F47-BE91-4A1F-B87D-B1302F038316}.Release|x86.Build.0 = Release|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|ARM64.Build.0 = Debug|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|x64.ActiveCfg = Debug|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|x64.Build.0 = Debug|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|x86.ActiveCfg = Debug|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Debug|x86.Build.0 = Debug|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|ARM64.ActiveCfg = Release|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|ARM64.Build.0 = Release|ARM64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|x64.ActiveCfg = Release|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|x64.Build.0 = Release|x64 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|x86.ActiveCfg = Release|Win32 + {124935CC-73BB-489E-92E8-4F922A85DB5D}.Release|x86.Build.0 = Release|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|ARM64.Build.0 = Debug|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|x64.ActiveCfg = Debug|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|x64.Build.0 = Debug|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|x86.ActiveCfg = Debug|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Debug|x86.Build.0 = Debug|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|ARM64.ActiveCfg = Release|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|ARM64.Build.0 = Release|ARM64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|x64.ActiveCfg = Release|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|x64.Build.0 = Release|x64 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|x86.ActiveCfg = Release|Win32 + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F}.Release|x86.Build.0 = Release|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|ARM64.Build.0 = Debug|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|x64.ActiveCfg = Debug|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|x64.Build.0 = Debug|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|x86.ActiveCfg = Debug|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Debug|x86.Build.0 = Debug|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|ARM64.ActiveCfg = Release|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|ARM64.Build.0 = Release|ARM64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|x64.ActiveCfg = Release|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|x64.Build.0 = Release|x64 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|x86.ActiveCfg = Release|Win32 + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}.Release|x86.Build.0 = Release|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|ARM64.Build.0 = Debug|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|x64.ActiveCfg = Debug|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|x64.Build.0 = Debug|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|x86.ActiveCfg = Debug|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Debug|x86.Build.0 = Debug|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|ARM64.ActiveCfg = Release|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|ARM64.Build.0 = Release|ARM64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x64.ActiveCfg = Release|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x64.Build.0 = Release|x64 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.ActiveCfg = Release|Win32 + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4830,7 +4960,7 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} @@ -4839,9 +4969,9 @@ Global {3B27F358-2679-4F38-B297-17B536F580BB} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {718FCBD0-591D-448C-B7D5-9F1CA8544E7B} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {278D8859-20B1-428F-8448-064F46E1F021} - {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} - {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {278D8859-20B1-428F-8448-064F46E1F021} + {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {278D8859-20B1-428F-8448-064F46E1F021} {8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021} {A4662163-83E7-4309-8CAA-B0BF13655FE6} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {5F4B766F-DD52-4B53-B6C3-BC7611E17F20} = {278D8859-20B1-428F-8448-064F46E1F021} @@ -4853,6 +4983,11 @@ Global {61997220-5383-4AE5-ABD4-5F45AE1B0F2A} = {278D8859-20B1-428F-8448-064F46E1F021} {7467E9AE-844F-444D-8A3F-17397544BA21} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {497FDF54-9762-4048-A833-61CC3980A0FB} = {278D8859-20B1-428F-8448-064F46E1F021} + {29B00F47-BE91-4A1F-B87D-B1302F038316} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} + {124935CC-73BB-489E-92E8-4F922A85DB5D} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021} + {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} = {278D8859-20B1-428F-8448-064F46E1F021} + {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {278D8859-20B1-428F-8448-064F46E1F021} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index e9a70930b..e55610a30 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -86,6 +86,7 @@ Example elements validated: | shapes_dashed_line | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_triangle_strip | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_vector_angle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_pie_chart | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -126,6 +127,7 @@ Example elements validated: | text_3d_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | text_codepoints_loading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | text_inline_styling | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| text_words_alignment | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_animation_playing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_billboard_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_box_collisions | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -196,3 +198,8 @@ Example elements validated: | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_starfield | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From af068ec020f2c57f0b4de228e8c2721c20aa6a94 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 15 Oct 2025 20:18:44 +0200 Subject: [PATCH 026/102] Reviewed dynamic library building #5270 --- src/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index e767d21d0..0d4ca9ac7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -519,7 +519,7 @@ endif #------------------------------------------------------------------------------------------------ LDFLAGS = $(CUSTOM_LDFLAGS) -L. -L$(RAYLIB_RELEASE_PATH) -ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) ifeq ($(PLATFORM_OS),WINDOWS) ifneq ($(CC), tcc) LDFLAGS += -Wl,--out-implib,$(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME)dll.a @@ -536,7 +536,6 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_SDL) - LDFLAGS += -Wl,-soname,lib$(RAYLIB_LIB_NAME).so.$(RAYLIB_API_VERSION) LDFLAGS += -L$(SDL_LIBRARY_PATH) endif ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) From c6f9f76afb0543d0091dedfbb1b549f1b45397e3 Mon Sep 17 00:00:00 2001 From: GideonSerf Date: Thu, 16 Oct 2025 09:53:55 +0200 Subject: [PATCH 027/102] [examples] Added donut pie charts to `shapes_pie_chart` (#5277) * Added donut chart option to pie chart example * Increased example description buffer size * Testing mouse trail building * Removed unused variable --------- Co-authored-by: Gideon Serfontein --- examples/shapes/shapes_mouse_trail.c | 6 +++--- examples/shapes/shapes_pie_chart.c | 26 +++++++++++++++++++++++--- examples/shapes/shapes_pie_chart.png | Bin 17457 -> 15301 bytes 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/examples/shapes/shapes_mouse_trail.c b/examples/shapes/shapes_mouse_trail.c index 88a7c0ce5..ad1166548 100644 --- a/examples/shapes/shapes_mouse_trail.c +++ b/examples/shapes/shapes_mouse_trail.c @@ -1,6 +1,3 @@ -#include "raylib.h" -#include "raymath.h" - /******************************************************************************************* * * raylib [shapes] example - Draw a mouse trail (position history) @@ -18,6 +15,9 @@ * ********************************************************************************************/ +#include "raylib.h" +#include "raymath.h" + // Define the maximum number of positions to store in the trail #define MAX_TRAIL_LENGTH 30 diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c index 35250c5be..1fa938905 100644 --- a/examples/shapes/shapes_pie_chart.c +++ b/examples/shapes/shapes_pie_chart.c @@ -36,6 +36,7 @@ int main(void) #define MAX_SLICES 10 int sliceCount = 7; + float donutInnerRadius = 25.0f; float values[MAX_SLICES] = {300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f}; //initial slice values char labels[MAX_SLICES][32]; bool editingLabel[MAX_SLICES] = {false}; @@ -45,6 +46,7 @@ int main(void) bool showValues = true; bool showPercentages = false; + bool showDonut = false; int hoveredSlice = -1; Rectangle scrollPanelBounds = {0}; Vector2 scrollContentOffset = {0}; @@ -72,7 +74,7 @@ int main(void) const Rectangle panelRect = { panelPos.x, panelPos.y, (float)panelWidth, - (float)screenHeight - 2.0f*panelMargin + (float)screenHeight - 2.0f*panelMargin }; // Pie chart geometry @@ -159,6 +161,12 @@ int main(void) DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 18, WHITE); } + if(showDonut) + { + // Draw inner circle to create donut effect + DrawCircle(center.x, center.y, donutInnerRadius, RAYWHITE); + } + startAngle += sweepAngle; } //------------------------------------------------------------------------------ @@ -177,17 +185,29 @@ int main(void) currentY += 30; GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Percentages", &showPercentages); - currentY += 40; + currentY += 30; + + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Make Donut", &showDonut); + currentY += 30; + + if(showDonut) + { + GuiSliderBar((Rectangle){ panelPos.x + 80, (float)currentY, panelRect.width - 100, 30 }, + "Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f); + currentY += 40; + } GuiLine((Rectangle){ panelPos.x + 10, (float)currentY, panelRect.width - 20, 1 }, NULL); currentY += 20; + + // Scrollable area for slice editors scrollPanelBounds = (Rectangle){ panelPos.x+panelMargin, (float)currentY, panelRect.width-panelMargin*2, panelRect.y + panelRect.height - currentY - panelMargin }; int contentHeight = sliceCount * 35; GuiScrollPanel(scrollPanelBounds, NULL, - (Rectangle){ 0, 0, panelRect.width - 20, (float)contentHeight }, + (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight }, &scrollContentOffset, &view); const float contentX = view.x + scrollContentOffset.x; // left of content diff --git a/examples/shapes/shapes_pie_chart.png b/examples/shapes/shapes_pie_chart.png index bad7960f476c0d66e32df5d38b7aded5a81b5a75..afc0a8c2d930a695661611746b3fb83083dc7eff 100644 GIT binary patch literal 15301 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 From 484cc0e25525c2b555db418e07537b0f0fd7e214 Mon Sep 17 00:00:00 2001 From: "Mr. Ai" Date: Thu, 16 Oct 2025 04:18:42 -0400 Subject: [PATCH 028/102] Fix DrawBillboardPro so that flipped images that are sampling from part of a larger texture still draw from the same source rectangle (#5276) Co-authored-by: Violently --- src/rmodels.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 3a5cc9004..3c904c396 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -3904,14 +3904,14 @@ void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector // Flip the content of the billboard while maintaining the counterclockwise edge rendering order if (size.x < 0.0f) { - source.x += size.x; + source.x -= size.x; source.width *= -1.0; right = Vector3Negate(right); origin.x *= -1.0f; } if (size.y < 0.0f) { - source.y += size.y; + source.y -= size.y; source.height *= -1.0; up = Vector3Negate(up); origin.y *= -1.0f; From 087aa1bc3f5333537dfe28d0d6fa4c114e17be4c Mon Sep 17 00:00:00 2001 From: Jopestpe <47086979+Jopestpe@users.noreply.github.com> Date: Fri, 17 Oct 2025 03:53:02 -0300 Subject: [PATCH 029/102] Fix triangle strip array size and simplify loop (#5280) --- examples/shapes/shapes_triangle_strip.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/examples/shapes/shapes_triangle_strip.c b/examples/shapes/shapes_triangle_strip.c index d8b5faeea..3172e1f7f 100644 --- a/examples/shapes/shapes_triangle_strip.c +++ b/examples/shapes/shapes_triangle_strip.c @@ -33,7 +33,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - triangle strip"); - Vector2 points[120] = { 0 }; + Vector2 points[122] = { 0 }; Vector2 center = { (screenWidth/2.0f) - 125.f, screenHeight/2.0f }; float segments = 6.0f; float insideRadius = 100.0f; @@ -69,17 +69,22 @@ int main(void) ClearBackground(RAYWHITE); - for (int i = 0, i2 = 0; i < pointCount; i++, i2 += 2) + for (int i = 0; i < pointCount; i++) { - float angle1 = i*angleStep; - Color color = ColorFromHSV(angle1*RAD2DEG, 1.0f, 1.0f); - DrawTriangle(points[i2 + 2], points[i2 + 1], points[i2], color); - if (outline) DrawTriangleLines(points[i2], points[i2 + 1], points[i2 + 2], BLACK); + Vector2 a = points[i*2]; + Vector2 b = points[i*2 + 1]; + Vector2 c = points[i*2 + 2]; + Vector2 d = points[i*2 + 3]; - float angle2 = angle1 + angleStep/2.0f; - color = ColorFromHSV(angle2*RAD2DEG, 1.0f, 1.0f); - DrawTriangle(points[i2 + 3], points[i2 + 1], points[i2 + 2], color); - if (outline) DrawTriangleLines(points[i2 + 2], points[i2 + 1], points[i2 + 3], BLACK); + float angle1 = i*angleStep; + DrawTriangle(c, b, a, ColorFromHSV(angle1*RAD2DEG, 1.0f, 1.0f)); + DrawTriangle(d, b, c, ColorFromHSV((angle1 + angleStep/2)*RAD2DEG, 1.0f, 1.0f)); + + if (outline) + { + DrawTriangleLines(a, b, c, BLACK); + DrawTriangleLines(c, b, d, BLACK); + } } DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); From 4256be560819e36c6d9b509802f5c0d2ba377edc Mon Sep 17 00:00:00 2001 From: Jopestpe <47086979+Jopestpe@users.noreply.github.com> Date: Fri, 17 Oct 2025 03:53:48 -0300 Subject: [PATCH 030/102] Fix branch array size and remove extra function (#5281) * Fix branch array size and remove extra function * Fix branch array size and remove extra function --- examples/shapes/shapes_recursive_tree.c | 33 +++++++++---------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/examples/shapes/shapes_recursive_tree.c b/examples/shapes/shapes_recursive_tree.c index 4d0042419..e9cadd8ec 100644 --- a/examples/shapes/shapes_recursive_tree.c +++ b/examples/shapes/shapes_recursive_tree.c @@ -31,11 +31,6 @@ typedef struct { float length; } Branch; -//---------------------------------------------------------------------------------- -// Module Functions Declaration -//---------------------------------------------------------------------------------- -static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length); - //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -64,13 +59,12 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - float theta = angle*DEG2RAD; int maxBranches = (int)(powf(2, floorf(treeDepth))); - Branch branches[1024] = { 0 }; + Branch branches[1030] = { 0 }; int count = 0; - Vector2 initialEnd = CalculateBranchEnd(start, 0.0f, length); + Vector2 initialEnd = { start.x + length*sinf(0.0f), start.y - length*cosf(0.0f) }; branches[count++] = (Branch){start, initialEnd, 0.0f, length}; for (int i = 0; i < count; i++) @@ -84,14 +78,16 @@ int main(void) { Vector2 branchStart = branch.end; - Vector2 branchEnd1 = CalculateBranchEnd(branchStart, branch.angle + theta, nextLength); - Vector2 branchEnd2 = CalculateBranchEnd(branchStart, branch.angle - theta, nextLength); - - branches[count++] = (Branch){branchStart, branchEnd1, branch.angle + theta, nextLength}; - branches[count++] = (Branch){branchStart, branchEnd2, branch.angle - theta, nextLength}; + float angle1 = branch.angle + theta; + Vector2 branchEnd1 = { branchStart.x + nextLength*sinf(angle1), branchStart.y - nextLength*cosf(angle1) }; + branches[count++] = (Branch){branchStart, branchEnd1, angle1, nextLength}; + + float angle2 = branch.angle - theta; + Vector2 branchEnd2 = { branchStart.x + nextLength*sinf(angle2), branchStart.y - nextLength*cosf(angle2) }; + branches[count++] = (Branch){branchStart, branchEnd2, angle2, nextLength}; } } - + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -103,8 +99,8 @@ int main(void) Branch branch = branches[i]; if (branch.length >= 2) { - if (!bezier) DrawLineEx(branch.start, branch.end, thick, RED); - else DrawLineBezier(branch.start, branch.end, thick, RED); + if (bezier) DrawLineBezier(branch.start, branch.end, thick, RED); + else DrawLineEx(branch.start, branch.end, thick, RED); } } @@ -133,9 +129,4 @@ int main(void) //-------------------------------------------------------------------------------------- return 0; -} - -static Vector2 CalculateBranchEnd(Vector2 start, float angle, float length) -{ - return (Vector2){ start.x + length*sinf(angle), start.y - length*cosf(angle) }; } \ No newline at end of file From 601ff4f02e51e545098ab7e57245fe8fb54ac8aa Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 09:54:49 +0200 Subject: [PATCH 031/102] REVIEW: Naming tweaks and comments added #5271 --- src/rlgl.h | 114 +++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/src/rlgl.h b/src/rlgl.h index 9cf8ebefb..dfdb26d32 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -785,8 +785,8 @@ RLAPI unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode); RLAPI unsigned int rlCompileShader(const char *shaderCode, int type); // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER) RLAPI unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program RLAPI void rlUnloadShaderProgram(unsigned int id); // Unload shader program -RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform -RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute +RLAPI int rlGetLocationUniform(unsigned int shaderId, const char *uniformName); // Get shader location uniform, requires shader program id +RLAPI int rlGetLocationAttrib(unsigned int shaderId, const char *attribName); // Get shader location attribute, requires shader program id 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 @@ -4238,121 +4238,121 @@ unsigned int rlLoadShaderCode(const char *vsCode, const char *fsCode) // Compile custom shader and return shader id unsigned int rlCompileShader(const char *shaderCode, int type) { - unsigned int shader = 0; + unsigned int shaderId = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - shader = glCreateShader(type); - glShaderSource(shader, 1, &shaderCode, NULL); + shaderId = glCreateShader(type); + glShaderSource(shaderId, 1, &shaderCode, NULL); GLint success = 0; - glCompileShader(shader); - glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + glCompileShader(shaderId); + glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); if (success == GL_FALSE) { switch (type) { - case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shader); break; - case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shader); break; + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile vertex shader code", shaderId); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile fragment shader code", shaderId); break; //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; + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to compile compute shader code", shaderId); break; #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; + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shaderId); break; #endif default: break; } int maxLength = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &maxLength); if (maxLength > 0) { int length = 0; char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); - glGetShaderInfoLog(shader, maxLength, &length, log); - TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shader, log); + glGetShaderInfoLog(shaderId, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Compile error: %s", shaderId, log); RL_FREE(log); } // Unload object allocated by glCreateShader(), // despite failing in the compilation process - glDeleteShader(shader); + glDeleteShader(shaderId); shader = 0; } else { switch (type) { - case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shader); break; - case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shader); break; + case GL_VERTEX_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Vertex shader compiled successfully", shaderId); break; + case GL_FRAGMENT_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Fragment shader compiled successfully", shaderId); break; //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; + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader compiled successfully", shaderId); break; #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; + case GL_COMPUTE_SHADER: TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43", shaderId); break; #endif default: break; } } #endif - return shader; + return shaderId; } // Load custom shader strings and return program id unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) { - unsigned int program = 0; + unsigned int programId = 0; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLint success = 0; - program = glCreateProgram(); + programId = glCreateProgram(); - glAttachShader(program, vShaderId); - glAttachShader(program, fShaderId); + glAttachShader(programId, vShaderId); + glAttachShader(programId, fShaderId); // NOTE: Default attribute shader locations must be Bound before linking - glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); - glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); - glBindAttribLocation(program, RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); - 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_INSTANCE_TX, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2, RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCE_TX, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE_TX); #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); + glBindAttribLocation(programId, RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEIDS, RL_DEFAULT_SHADER_ATTRIB_NAME_BONEIDS); + glBindAttribLocation(programId, 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 - glLinkProgram(program); + glLinkProgram(programId); // NOTE: All uniform variables are intitialised to 0 when a program links - glGetProgramiv(program, GL_LINK_STATUS, &success); + glGetProgramiv(programId, GL_LINK_STATUS, &success); if (success == GL_FALSE) { - TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", program); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link shader program", programId); int maxLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &maxLength); if (maxLength > 0) { int length = 0; char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); - glGetProgramInfoLog(program, maxLength, &length, log); - TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); + glGetProgramInfoLog(programId, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", programId, log); RL_FREE(log); } - glDeleteProgram(program); + glDeleteProgram(programId); - program = 0; + programId = 0; } else { @@ -4361,10 +4361,10 @@ unsigned int rlLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId) //GLint binarySize = 0; //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); - TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", program); + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully", programId); } #endif - return program; + return programId; } // Unload shader program @@ -4378,6 +4378,7 @@ void rlUnloadShaderProgram(unsigned int id) } // Get shader location uniform +// NOTE: First parameter refers to shader program id int rlGetLocationUniform(unsigned int shaderId, const char *uniformName) { int location = -1; @@ -4391,6 +4392,7 @@ int rlGetLocationUniform(unsigned int shaderId, const char *uniformName) } // Get shader location attribute +// NOTE: First parameter refers to shader program id int rlGetLocationAttrib(unsigned int shaderId, const char *attribName) { int location = -1; @@ -4516,37 +4518,37 @@ void rlSetShader(unsigned int id, int *locs) // Load compute shader program unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) { - unsigned int program = 0; + unsigned int programId = 0; #if defined(GRAPHICS_API_OPENGL_43) GLint success = 0; - program = glCreateProgram(); - glAttachShader(program, shaderId); - glLinkProgram(program); + programId = glCreateProgram(); + glAttachShader(programId, shaderId); + glLinkProgram(programId); // NOTE: All uniform variables are intitialised to 0 when a program links - glGetProgramiv(program, GL_LINK_STATUS, &success); + glGetProgramiv(programId, GL_LINK_STATUS, &success); if (success == GL_FALSE) { - TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", program); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to link compute shader program", programId); int maxLength = 0; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &maxLength); if (maxLength > 0) { int length = 0; char *log = (char *)RL_CALLOC(maxLength, sizeof(char)); - glGetProgramInfoLog(program, maxLength, &length, log); - TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", program, log); + glGetProgramInfoLog(programId, maxLength, &length, log); + TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Link error: %s", programId, log); RL_FREE(log); } - glDeleteProgram(program); + glDeleteProgram(programId); - program = 0; + programId = 0; } else { @@ -4555,13 +4557,13 @@ unsigned int rlLoadComputeShaderProgram(unsigned int shaderId) //GLint binarySize = 0; //glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize); - TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", program); + TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Compute shader program loaded successfully", programId); } #else TRACELOG(RL_LOG_WARNING, "SHADER: Compute shaders not enabled. Define GRAPHICS_API_OPENGL_43"); #endif - return program; + return programId; } // Dispatch compute shader (equivalent to *draw* for graphics pilepine) From 311f6243e3dd242d03a114385253a2409be291bc Mon Sep 17 00:00:00 2001 From: MULTi <78434796+MULTidll@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:31:24 +0530 Subject: [PATCH 032/102] Disable touch position simulation from mouse movement for DRM touchscreen devices (#5279) --- src/platforms/rcore_drm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index e067fd82a..58e820af1 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -1130,11 +1130,12 @@ void PollInputEvents(void) // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; - // Reset touch positions - //for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ 0, 0 }; + // Reset touch positions to invalid state + for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.position[i] = (Vector2){ -1, -1 }; // Map touch position to mouse position for convenience - CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; + // NOTE: For DRM touchscreen devices, this mapping is disabled to avoid false touch detection + // CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; // Handle the mouse/touch/gestures events: PollMouseEvents(); @@ -2262,7 +2263,8 @@ static void PollMouseEvents(void) } else CORE.Input.Mouse.currentPosition.x += event.value; - CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x; + // NOTE: For DRM touchscreen, do not simulate touch from mouse movement + // CORE.Input.Touch.position[0].x = CORE.Input.Mouse.currentPosition.x; touchAction = 2; // TOUCH_ACTION_MOVE } @@ -2275,7 +2277,8 @@ static void PollMouseEvents(void) } else CORE.Input.Mouse.currentPosition.y += event.value; - CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y; + // NOTE: For DRM touchscreen, do not simulate touch from mouse movement + // CORE.Input.Touch.position[0].y = CORE.Input.Mouse.currentPosition.y; touchAction = 2; // TOUCH_ACTION_MOVE } From 9ed785c2e1de44ca4f4b0130ac7538bbb8f596d2 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 10:04:21 +0200 Subject: [PATCH 033/102] 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 dfdb26d32..f587d81a2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -4278,7 +4278,7 @@ unsigned int rlCompileShader(const char *shaderCode, int type) // Unload object allocated by glCreateShader(), // despite failing in the compilation process glDeleteShader(shaderId); - shader = 0; + shaderId = 0; } else { From bb910bb0b8624a8e58fa3adce2e2ce5cadeb0ab2 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 12:33:41 +0200 Subject: [PATCH 034/102] REXM: RENAME: example: `models_geometry_textures_cube` --> `models_rotating_cube` --- examples/Makefile | 2 +- examples/Makefile.Web | 4 ++-- examples/README.md | 2 +- examples/examples_list.txt | 2 +- ...try_textures_cube.c => models_rotating_cube.c} | 14 ++++++++++---- ...textures_cube.png => models_rotating_cube.png} | Bin ..._cube.vcxproj => models_rotating_cube.vcxproj} | 6 +++--- projects/VS2022/raylib.sln | 2 +- 8 files changed, 19 insertions(+), 13 deletions(-) rename examples/models/{models_geometry_textures_cube.c => models_rotating_cube.c} (84%) rename examples/models/{models_geometry_textures_cube.png => models_rotating_cube.png} (100%) rename projects/VS2022/examples/{models_geometry_textures_cube.vcxproj => models_rotating_cube.vcxproj} (99%) diff --git a/examples/Makefile b/examples/Makefile index eb6725756..332e6c9d5 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -630,7 +630,7 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_geometry_textures_cube \ + models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index e365a5fee..5b34c34c7 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -630,7 +630,7 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_geometry_textures_cube \ + models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ @@ -1146,7 +1146,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_geometry_textures_cube: models/models_geometry_textures_cube.c +models/models_rotating_cube: models/models_rotating_cube.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png diff --git a/examples/README.md b/examples/README.md index e8b6ba4bf..13f39c503 100644 --- a/examples/README.md +++ b/examples/README.md @@ -191,7 +191,7 @@ Examples using raylib models functionality, including models loading/generation | [models_bone_socket](models/models_bone_socket.c) | models_bone_socket | ⭐⭐⭐⭐️ | 4.5 | 4.5 | [iP](https://github.com/ipzaur) | | [models_tesseract_view](models/models_tesseract_view.c) | models_tesseract_view | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) | | [models_basic_voxel](models/models_basic_voxel.c) | models_basic_voxel | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) | -| [models_geometry_textures_cube](models/models_geometry_textures_cube.c) | models_geometry_textures_cube | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | +| [models_rotating_cube](models/models_rotating_cube.c) | models_rotating_cube | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | ### category: shaders [30] diff --git a/examples/examples_list.txt b/examples/examples_list.txt index b86a4bc02..7d55d09cf 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -139,7 +139,7 @@ models;models_animation_gpu_skinning;★★★☆;4.5;4.5;2024;2025;"Daniel Hold models;models_bone_socket;★★★★;4.5;4.5;2024;2025;"iP";@ipzaur models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle -models;models_geometry_textures_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe +models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/models/models_geometry_textures_cube.c b/examples/models/models_rotating_cube.c similarity index 84% rename from examples/models/models_geometry_textures_cube.c rename to examples/models/models_rotating_cube.c index 9441c7fd4..930dae516 100644 --- a/examples/models/models_geometry_textures_cube.c +++ b/examples/models/models_rotating_cube.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [models] example - geometry textures cube +* raylib [models] example - rotating cube * * Example complexity rating: [★☆☆☆] 1/4 * @@ -27,11 +27,11 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [models] example - geometry textures cube"); + InitWindow(screenWidth, screenHeight, "raylib [models] example - rotating cube"); // Define the camera to look into our 3d world Camera camera = { 0 }; - camera.position = (Vector3){ 0.0f, 0.0f, 4.0f }; + camera.position = (Vector3){ 0.0f, 3.0f, 3.0f }; camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; camera.fovy = 45.0f; @@ -58,6 +58,7 @@ int main(void) // Update //---------------------------------------------------------------------------------- rotation += 1.0f; + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- @@ -67,7 +68,11 @@ int main(void) BeginMode3D(camera); - DrawModelEx(model, (Vector3){0,0,0}, (Vector3){0.5f,1,0}, rotation, (Vector3){1,1,1}, WHITE); + // Draw model defining: position, size, rotation-axis, rotation (degrees), size, and tint-color + DrawModelEx(model, (Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.5f, 1.0f, 0.0f }, + rotation, (Vector3){ 1.0f, 1.0f, 1.0f }, WHITE); + + DrawGrid(10, 1.0f); EndMode3D(); @@ -81,6 +86,7 @@ int main(void) //-------------------------------------------------------------------------------------- UnloadTexture(texture); // Unload texture UnloadModel(model); // Unload model + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_geometry_textures_cube.png b/examples/models/models_rotating_cube.png similarity index 100% rename from examples/models/models_geometry_textures_cube.png rename to examples/models/models_rotating_cube.png diff --git a/projects/VS2022/examples/models_geometry_textures_cube.vcxproj b/projects/VS2022/examples/models_rotating_cube.vcxproj similarity index 99% rename from projects/VS2022/examples/models_geometry_textures_cube.vcxproj rename to projects/VS2022/examples/models_rotating_cube.vcxproj index 77fcd94d4..ebf5f10f7 100644 --- a/projects/VS2022/examples/models_geometry_textures_cube.vcxproj +++ b/projects/VS2022/examples/models_rotating_cube.vcxproj @@ -53,9 +53,9 @@ {A4662163-83E7-4309-8CAA-B0BF13655FE6} Win32Proj - models_geometry_textures_cube + models_rotating_cube 10.0 - models_geometry_textures_cube + models_rotating_cube @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 5a784adbe..601b3d409 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -357,7 +357,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_basic_voxel", "examp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_dashed_line", "examples\shapes_dashed_line.vcxproj", "{8E132D5A-2C00-48D0-8747-97E41356F26F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_geometry_textures_cube", "examples\models_geometry_textures_cube.vcxproj", "{A4662163-83E7-4309-8CAA-B0BF13655FE6}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_rotating_cube", "examples\models_rotating_cube.vcxproj", "{A4662163-83E7-4309-8CAA-B0BF13655FE6}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{5F4B766F-DD52-4B53-B6C3-BC7611E17F20}" EndProject From 0c97c95f6c462582a2404f9de2401b189c3e11bc Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 12:33:50 +0200 Subject: [PATCH 035/102] Update rexm.c --- tools/rexm/rexm.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 2dc295f37..c615e810f 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -224,6 +224,7 @@ int main(int argc, char *argv[]) char exRebuildRequested[16] = { 0 }; // Example category/full rebuild request int opCode = OP_NONE; // Operation code: 0-None(Help), 1-Create, 2-Add, 3-Rename, 4-Remove + bool showUsage = false; // Flag to show usage help bool verbose = false; // Flag for verbose log info // Command-line usage mode: command args processing @@ -231,12 +232,14 @@ int main(int argc, char *argv[]) if (argc > 1) { // Supported commands: - // help : Provides command-line usage information (default) // create : Creates an empty example, from internal template // add : Add existing example, category extracted from name // rename : Rename an existing example // remove : Remove an existing example - // validate : Validate examples collection + // build : Build example for Desktop and Web platforms + // validate : Validate examples collection, generates report + // update : Validate and update examples collection, generates report + if (strcmp(argv[1], "create") == 0) { // Check for valid upcoming argument @@ -410,11 +413,18 @@ int main(int argc, char *argv[]) } } } - - // Check for verbose log mode request + + // Process command line options arguments for (int i = 1; i < argc; i++) { - if ((strcmp(argv[i], "-v") == 0) || (strcmp(argv[i], "--verbose") == 0)) verbose = true; + if ((strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "--help") == 0)) + { + showUsage = true; + } + else if ((strcmp(argv[i], "-v") == 0) || (strcmp(argv[i], "--verbose") == 0)) + { + verbose = true; + } } } @@ -1372,7 +1382,6 @@ int main(int argc, char *argv[]) default: // Help { // Supported commands: - // help : Provides command-line usage information // create : Creates an empty example, from internal template // add : Add existing example, category extracted from name // rename : Rename an existing example @@ -1394,7 +1403,6 @@ int main(int argc, char *argv[]) printf(" > rexm []\n\n"); printf("COMMANDS:\n\n"); - printf(" help : Provides command-line usage information\n"); printf(" create : Creates an empty example, from internal template\n"); printf(" add : Add existing example, category extracted from name\n"); printf(" Supported categories: core, shapes, textures, text, models\n"); @@ -1403,6 +1411,9 @@ int main(int argc, char *argv[]) printf(" build : Build example for Desktop and Web platforms\n"); printf(" validate : Validate examples collection, generates report\n"); printf(" update : Validate and update examples collection, generates report\n\n"); + printf("OPTIONS:\n\n"); + printf(" -h, --help : Show tool version and command line usage help\n"); + printf(" -v, --verbose : Verbose mode, show additional logs on processes\n"); printf("\nEXAMPLES:\n\n"); printf(" > rexm add shapes_custom_stars\n"); printf(" Add and updates new example provided \n\n"); From 9c1216699d84b2d5e18e766b77d3f32fe51a89e7 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 12:35:12 +0200 Subject: [PATCH 036/102] ADDED: example: `core_highdpi_testbed` -WIP- ADDED: example: `core_screen_recording` -WIP- --- examples/Makefile | 2 + examples/Makefile.Web | 8 + examples/README.md | 6 +- examples/core/core_highdpi_testbed.c | 70 +++ examples/core/core_highdpi_testbed.png | Bin 0 -> 17323 bytes examples/core/core_screen_recording.c | 70 +++ examples/core/core_screen_recording.png | Bin 0 -> 17323 bytes examples/examples_list.txt | 2 + .../examples/core_highdpi_testbed.vcxproj | 569 ++++++++++++++++++ .../examples/core_screen_recording.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 54 ++ 11 files changed, 1348 insertions(+), 2 deletions(-) create mode 100644 examples/core/core_highdpi_testbed.c create mode 100644 examples/core/core_highdpi_testbed.png create mode 100644 examples/core/core_screen_recording.c create mode 100644 examples/core/core_screen_recording.png create mode 100644 projects/VS2022/examples/core_highdpi_testbed.vcxproj create mode 100644 projects/VS2022/examples/core_screen_recording.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 332e6c9d5..498a36f47 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -519,6 +519,7 @@ CORE = \ core/core_directory_files \ core/core_drop_files \ core/core_high_dpi \ + core/core_highdpi_testbed \ core/core_input_actions \ core/core_input_gamepad \ core/core_input_gestures \ @@ -533,6 +534,7 @@ CORE = \ core/core_random_values \ core/core_render_texture \ core/core_scissor_test \ + core/core_screen_recording \ core/core_smooth_pixelperfect \ core/core_storage_values \ core/core_undo_redo \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 5b34c34c7..1b32ebddf 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -519,6 +519,7 @@ CORE = \ core/core_directory_files \ core/core_drop_files \ core/core_high_dpi \ + core/core_highdpi_testbed \ core/core_input_actions \ core/core_input_gamepad \ core/core_input_gestures \ @@ -533,6 +534,7 @@ CORE = \ core/core_random_values \ core/core_render_texture \ core/core_scissor_test \ + core/core_screen_recording \ core/core_smooth_pixelperfect \ core/core_storage_values \ core/core_undo_redo \ @@ -761,6 +763,9 @@ core/core_drop_files: core/core_drop_files.c core/core_high_dpi: core/core_high_dpi.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_highdpi_testbed: core/core_highdpi_testbed.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + core/core_input_actions: core/core_input_actions.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -805,6 +810,9 @@ core/core_render_texture: core/core_render_texture.c core/core_scissor_test: core/core_scissor_test.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_screen_recording: core/core_screen_recording.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + core/core_smooth_pixelperfect: core/core_smooth_pixelperfect.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 13f39c503..dbc36fe22 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 183] +## EXAMPLES COLLECTION [TOTAL: 185] -### category: core [42] +### category: core [44] Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. @@ -66,6 +66,8 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | +| [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | +| [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | ### category: shapes [31] diff --git a/examples/core/core_highdpi_testbed.c b/examples/core/core_highdpi_testbed.c new file mode 100644 index 000000000..b22aa507a --- /dev/null +++ b/examples/core/core_highdpi_testbed.c @@ -0,0 +1,70 @@ +/******************************************************************************************* +* +* raylib [core] example - highdpi testbed +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* +* Example contributed by (@) 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) 0 (@) +* +********************************************************************************************/ + +#include "raylib.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - highdpi testbed"); + + // TODO: Load resources / Initialize variables at this point + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update variables / Implement example logic at this point + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // TODO: Draw everything that requires to be drawn at this point + + DrawLineEx((Vector2){ 0, 0 }, (Vector2){ screenWidth, screenHeight }, 2.0f, RED); + DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED); + DrawText("example base code template", 260, 400, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // TODO: Unload all loaded resources at this point + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/core/core_highdpi_testbed.png b/examples/core/core_highdpi_testbed.png new file mode 100644 index 0000000000000000000000000000000000000000..da99bbb0d97118eef3ca41c16b62182acced63f9 GIT binary patch literal 17323 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 (@) 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) 0 (@) +* +********************************************************************************************/ + +#include "raylib.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - screen recording"); + + // TODO: Load resources / Initialize variables at this point + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // TODO: Update variables / Implement example logic at this point + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // TODO: Draw everything that requires to be drawn at this point + + DrawLineEx((Vector2){ 0, 0 }, (Vector2){ screenWidth, screenHeight }, 2.0f, RED); + DrawLineEx((Vector2){ 0, screenHeight }, (Vector2){ screenWidth, 0 }, 2.0f, RED); + DrawText("example base code template", 260, 400, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // TODO: Unload all loaded resources at this point + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/core/core_screen_recording.png b/examples/core/core_screen_recording.png new file mode 100644 index 0000000000000000000000000000000000000000..da99bbb0d97118eef3ca41c16b62182acced63f9 GIT binary patch literal 17323 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";@ +core;core_screen_recording;★☆☆☆;5.5;5.6;0;0;"";@ shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower diff --git a/projects/VS2022/examples/core_highdpi_testbed.vcxproj b/projects/VS2022/examples/core_highdpi_testbed.vcxproj new file mode 100644 index 000000000..89675f5ed --- /dev/null +++ b/projects/VS2022/examples/core_highdpi_testbed.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + core_highdpi_testbed + 10.0 + core_highdpi_testbed + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/core_screen_recording.vcxproj b/projects/VS2022/examples/core_screen_recording.vcxproj new file mode 100644 index 000000000..1669c6ac7 --- /dev/null +++ b/projects/VS2022/examples/core_screen_recording.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + core_screen_recording + 10.0 + core_screen_recording + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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 601b3d409..20b7ad9bb 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -387,6 +387,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_mouse_trail", "examp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield", "examples\shapes_starfield.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "examples\core_highdpi_testbed.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "examples\core_screen_recording.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4793,6 +4797,54 @@ Global {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x64.Build.0 = Release|x64 {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.ActiveCfg = Release|Win32 {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 + {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4988,6 +5040,8 @@ Global {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021} {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} = {278D8859-20B1-428F-8448-064F46E1F021} {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {278D8859-20B1-428F-8448-064F46E1F021} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From ffc405325f51a39d1ed3770c797f11bac8e3c089 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 12:54:46 +0200 Subject: [PATCH 037/102] Update shapes_pie_chart.c --- examples/shapes/shapes_pie_chart.c | 242 ++++++++++++++--------------- 1 file changed, 113 insertions(+), 129 deletions(-) diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c index 1fa938905..e2f6900eb 100644 --- a/examples/shapes/shapes_pie_chart.c +++ b/examples/shapes/shapes_pie_chart.c @@ -22,6 +22,8 @@ #define RAYGUI_IMPLEMENTATION #include "raygui.h" +#define MAX_PIE_SLICES 10 // Max pie slices + //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -34,15 +36,14 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shapes] example - pie chart"); - #define MAX_SLICES 10 int sliceCount = 7; float donutInnerRadius = 25.0f; - float values[MAX_SLICES] = {300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f}; //initial slice values - char labels[MAX_SLICES][32]; - bool editingLabel[MAX_SLICES] = {false}; + float values[MAX_PIE_SLICES] = { 300.0f, 100.0f, 450.0f, 350.0f, 600.0f, 380.0f, 750.0f }; // Initial slice values + char labels[MAX_PIE_SLICES][32] = { 0 }; + bool editingLabel[MAX_PIE_SLICES] = { 0 }; - for (int i = 0; i < MAX_SLICES; i++) - snprintf(labels[i], 32, "Slice %i", i + 1); + for (int i = 0; i < MAX_PIE_SLICES; i++) + snprintf(labels[i], 32, "Slice %02i", i + 1); bool showValues = true; bool showPercentages = false; @@ -50,7 +51,32 @@ int main(void) int hoveredSlice = -1; Rectangle scrollPanelBounds = {0}; Vector2 scrollContentOffset = {0}; - Rectangle view = {0}; + Rectangle view = { 0 }; + + // UI layout parameters + const int panelWidth = 270; + const int panelMargin = 5; + + // UI Panel top-left anchor + const Vector2 panelPos = { + (float)screenWidth - panelMargin - panelWidth, + (float)panelMargin + }; + + // UI Panel rectangle + const Rectangle panelRect = { + panelPos.x, panelPos.y, + (float)panelWidth, + (float)screenHeight - 2.0f*panelMargin + }; + + // Pie chart geometry + const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight }; + const Vector2 center = { canvas.width/2.0f, canvas.height/2.0f}; + const float radius = 205.0f; + + // Total value for percentage calculations + float totalValue = 0.0f; SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -60,32 +86,9 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - //UI layout parameters - const int panelWidth = 270; - const int panelMargin = 5; - - // UI Panel top-left anchor - const Vector2 panelPos = { - (float)screenWidth - panelMargin - panelWidth, - (float)panelMargin - }; - - // UI Panel rectangle - const Rectangle panelRect = { - panelPos.x, panelPos.y, - (float)panelWidth, - (float)screenHeight - 2.0f*panelMargin - }; - - // Pie chart geometry - const Rectangle canvas = { 0, 0, panelPos.x, (float)screenHeight }; - const Vector2 center = {canvas.width / 2.0f, canvas.height / 2.0f}; - const float radius = 205.0f; - // Calculate total value for percentage calculations - float totalValue = 0.0f; - for (int i = 0; i < sliceCount; i++) - totalValue += values[i]; + totalValue = 0.0f; + for (int i = 0; i < sliceCount; i++) totalValue += values[i]; // Check for mouse hover over slices hoveredSlice = -1; // Reset hovered slice @@ -94,23 +97,24 @@ int main(void) { float dx = mousePos.x - center.x; float dy = mousePos.y - center.y; - float distance = sqrtf(dx * dx + dy * dy); + float distance = sqrtf(dx*dx + dy*dy); if (distance <= radius) // Inside the pie radius { - float angle = atan2f(dy, dx) * RAD2DEG; - if (angle < 0) - angle += 360; + float angle = atan2f(dy, dx)*RAD2DEG; + if (angle < 0) angle += 360; float currentAngle = 0.0f; for (int i = 0; i < sliceCount; i++) { - float sweep = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f; - if (angle >= currentAngle && angle < (currentAngle + sweep)) + float sweep = (totalValue > 0)? (values[i]/totalValue)*360.0f : 0.0f; + + if ((angle >= currentAngle) && (angle < (currentAngle + sweep))) { hoveredSlice = i; break; } + currentAngle += sweep; } } @@ -120,116 +124,96 @@ int main(void) // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(RAYWHITE); + ClearBackground(RAYWHITE); - // Draw the pie chart on the canvas - //------------------------------------------------------------------------------ - float startAngle = 0.0f; - for (int i = 0; i < sliceCount; i++) - { - float sweepAngle = (totalValue > 0) ? (values[i] / totalValue) * 360.0f : 0.0f; - float midAngle = startAngle + sweepAngle / 2.0f; // Middle angle for label positioning - - Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f); - float currentRadius = radius; - - // Make the hovered slice pop out by adding 5 pixels to its radius - if (i == hoveredSlice) - currentRadius += 5.0f; - - // Draw the pie slice using raylib's DrawCircleSector function - DrawCircleSector(center, currentRadius, startAngle, startAngle + sweepAngle, 120, color); - - // Draw the label for the current slice - if (values[i] > 0) + // Draw the pie chart on the canvas + float startAngle = 0.0f; + for (int i = 0; i < sliceCount; i++) { - char labelText[64]; - if (showValues && showPercentages) - snprintf(labelText, 64, "%.1f (%.0f%%)", values[i], (values[i] / totalValue) * 100.0f); - else if (showValues) - snprintf(labelText, 64, "%.1f", values[i]); - else if (showPercentages) - snprintf(labelText, 64, "%.0f%%", (values[i] / totalValue) * 100.0f); - else - labelText[0] = '\0'; + float sweepAngle = (totalValue > 0)? (values[i]/totalValue)*360.0f : 0.0f; + float midAngle = startAngle + sweepAngle/2.0f; // Middle angle for label positioning - Vector2 textSize = MeasureTextEx(GetFontDefault(), labelText, 18, 1); - float labelRadius = radius * 0.7f; - Vector2 labelPos = { - center.x + cosf(midAngle * DEG2RAD) * labelRadius - textSize.x / 2, - center.y + sinf(midAngle * DEG2RAD) * labelRadius - textSize.y / 2}; - DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 18, WHITE); - } + Color color = ColorFromHSV((float)i/sliceCount*360.0f, 0.75f, 0.9f); + float currentRadius = radius; + + // Make the hovered slice pop out by adding 5 pixels to its radius + if (i == hoveredSlice) currentRadius += 20.0f; + + // Draw the pie slice using raylib's DrawCircleSector function + DrawCircleSector(center, currentRadius, startAngle, startAngle + sweepAngle, 120, color); + + // Draw the label for the current slice + if (values[i] > 0) + { + char labelText[64] = { 0 }; + if (showValues && showPercentages) snprintf(labelText, 64, "%.1f (%.0f%%)", values[i], (values[i]/totalValue)*100.0f); + else if (showValues) snprintf(labelText, 64, "%.1f", values[i]); + else if (showPercentages) snprintf(labelText, 64, "%.0f%%", (values[i]/totalValue)*100.0f); + else labelText[0] = '\0'; + + Vector2 textSize = MeasureTextEx(GetFontDefault(), labelText, 20, 1); + float labelRadius = radius*0.7f; + Vector2 labelPos = { center.x + cosf(midAngle*DEG2RAD)*labelRadius - textSize.x/2.0f, + center.y + sinf(midAngle*DEG2RAD)*labelRadius - textSize.y/2.0f }; + DrawText(labelText, (int)labelPos.x, (int)labelPos.y, 20, WHITE); + } - if(showDonut) - { // Draw inner circle to create donut effect - DrawCircle(center.x, center.y, donutInnerRadius, RAYWHITE); + // TODO: This is a hacky solution, better use DrawRing() + if (showDonut) DrawCircle(center.x, center.y, donutInnerRadius, RAYWHITE); + + startAngle += sweepAngle; } - startAngle += sweepAngle; - } - //------------------------------------------------------------------------------ + // UI control panel + DrawRectangleRec(panelRect, Fade(LIGHTGRAY, 0.5f)); + DrawRectangleLinesEx(panelRect, 1.0f, GRAY); - // UI control panel - //------------------------------------------------------------------------------ - DrawRectangleRec(panelRect, Fade(LIGHTGRAY, 0.5f)); - DrawRectangleLinesEx(panelRect, 1.0f, GRAY); + GuiSpinner((Rectangle){ panelPos.x + 95, (float)panelPos.y + 12, 125, 25 }, "Slices ", &sliceCount, 1, MAX_PIE_SLICES, false); + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 40, 20, 20 }, "Show Values", &showValues); + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 70, 20, 20 }, "Show Percentages", &showPercentages); + GuiCheckBox((Rectangle){ panelPos.x + 20, (float)panelPos.y + 12 + 100, 20, 20 }, "Make Donut", &showDonut); - int currentY = (int)panelPos.y + 12; // Start a bit lower for margin + if (showDonut) GuiDisable(); + GuiSliderBar((Rectangle){ panelPos.x + 80, (float)panelPos.y + 12 + 130, panelRect.width - 100, 30 }, + "Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f); + GuiEnable(); - GuiSpinner((Rectangle){ panelPos.x + 95, (float)currentY, 125, 25 }, "Slices ", &sliceCount, 1, MAX_SLICES, false); - currentY += 40; + GuiLine((Rectangle){ panelPos.x + 10, (float)panelPos.y + 12 + 170, panelRect.width - 20, 1 }, NULL); - GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Values", &showValues); - currentY += 30; + // Scrollable area for slice editors + scrollPanelBounds = (Rectangle){ + panelPos.x + panelMargin, + (float)panelPos.y + 12 + 190, + panelRect.width - panelMargin*2, + panelRect.y + panelRect.height - panelPos.y + 12 + 190 - panelMargin + }; + int contentHeight = sliceCount*35; - GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Show Percentages", &showPercentages); - currentY += 30; + GuiScrollPanel(scrollPanelBounds, NULL, + (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight }, + &scrollContentOffset, &view); - GuiCheckBox((Rectangle){ panelPos.x + 20, (float)currentY, 20, 20 }, "Make Donut", &showDonut); - currentY += 30; + const float contentX = view.x + scrollContentOffset.x; // Left of content + const float contentY = view.y + scrollContentOffset.y; // Top of content - if(showDonut) - { - GuiSliderBar((Rectangle){ panelPos.x + 80, (float)currentY, panelRect.width - 100, 30 }, - "Inner Radius", NULL, &donutInnerRadius, 5.0f, radius - 10.0f); - currentY += 40; - } + BeginScissorMode((int)view.x, (int)view.y, (int)view.width, (int)view.height); - GuiLine((Rectangle){ panelPos.x + 10, (float)currentY, panelRect.width - 20, 1 }, NULL); - currentY += 20; + for (int i = 0; i < sliceCount; i++) + { + const int rowY = (int)(contentY + 5 + i*35); - + // Color indicator + Color color = ColorFromHSV((float)i/sliceCount*360.0f, 0.75f, 0.9f); + DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color); - // Scrollable area for slice editors - scrollPanelBounds = (Rectangle){ panelPos.x+panelMargin, (float)currentY, panelRect.width-panelMargin*2, panelRect.y + panelRect.height - currentY - panelMargin }; - int contentHeight = sliceCount * 35; + // Label textbox + if (GuiTextBox((Rectangle){ contentX + 45, (float)rowY, 75, 30 }, labels[i], 32, editingLabel[i])) editingLabel[i] = !editingLabel[i]; - GuiScrollPanel(scrollPanelBounds, NULL, - (Rectangle){ 0, 0, panelRect.width - 25, (float)contentHeight }, - &scrollContentOffset, &view); + GuiSliderBar((Rectangle){ contentX + 130, (float)rowY, 110, 30 }, NULL, NULL, &values[i], 0.0f, 1000.0f); + } - const float contentX = view.x + scrollContentOffset.x; // left of content - const float contentY = view.y + scrollContentOffset.y; // top of content - - BeginScissorMode((int)view.x, (int)view.y, (int)view.width, (int)view.height); - for (int i = 0; i < sliceCount; i++) - { - const int rowY = (int)(contentY + 5 + i * 35); - - // Color indicator - Color color = ColorFromHSV((float)i / sliceCount * 360.0f, 0.75f, 0.9f); - DrawRectangle((int)(contentX + 15), rowY + 5, 20, 20, color); - - // Label textbox - if (GuiTextBox((Rectangle){contentX + 45, (float)rowY, 75, 30}, labels[i], 32, editingLabel[i])) - editingLabel[i] = !editingLabel[i]; - - GuiSliderBar((Rectangle){contentX + 130, (float)rowY, 110, 30}, - NULL, NULL, &values[i], 0.0f, 1000.0f); - } - EndScissorMode(); + EndScissorMode(); EndDrawing(); //---------------------------------------------------------------------------------- From 4099218f1a5f1aaf96e6e5c646585a50d053c688 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 12:55:13 +0200 Subject: [PATCH 038/102] Update new examples UUID --- .../examples/core_highdpi_testbed.vcxproj | 2 +- .../examples/core_screen_recording.vcxproj | 2 +- projects/VS2022/raylib.sln | 106 +++++++++--------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/projects/VS2022/examples/core_highdpi_testbed.vcxproj b/projects/VS2022/examples/core_highdpi_testbed.vcxproj index 89675f5ed..d50de0d6e 100644 --- a/projects/VS2022/examples/core_highdpi_testbed.vcxproj +++ b/projects/VS2022/examples/core_highdpi_testbed.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F} Win32Proj core_highdpi_testbed 10.0 diff --git a/projects/VS2022/examples/core_screen_recording.vcxproj b/projects/VS2022/examples/core_screen_recording.vcxproj index 1669c6ac7..7b5856dbd 100644 --- a/projects/VS2022/examples/core_screen_recording.vcxproj +++ b/projects/VS2022/examples/core_screen_recording.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {9DE2FC01-A839-4F89-8319-9071D4C54821} Win32Proj core_screen_recording 10.0 diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 20b7ad9bb..be06d43a2 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -387,9 +387,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_mouse_trail", "examp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield", "examples\shapes_starfield.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "examples\core_highdpi_testbed.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "examples\core_highdpi_testbed.vcxproj", "{1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "examples\core_screen_recording.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "examples\core_screen_recording.vcxproj", "{9DE2FC01-A839-4F89-8319-9071D4C54821}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -4797,54 +4797,54 @@ Global {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x64.Build.0 = Release|x64 {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.ActiveCfg = Release|Win32 {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|ARM64.Build.0 = Debug|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.ActiveCfg = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x64.Build.0 = Debug|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.ActiveCfg = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Debug|x86.Build.0 = Debug|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x64.Build.0 = Release.DLL|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release.DLL|x86.Build.0 = Release.DLL|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.ActiveCfg = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|ARM64.Build.0 = Release|ARM64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.ActiveCfg = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x64.Build.0 = Release|x64 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.ActiveCfg = Release|Win32 - {6B1A933E-71B8-4C1F-9E79-02D98830E671}.Release|x86.Build.0 = Release|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|ARM64.Build.0 = Debug|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|x64.ActiveCfg = Debug|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|x64.Build.0 = Debug|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|x86.ActiveCfg = Debug|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Debug|x86.Build.0 = Debug|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|ARM64.ActiveCfg = Release|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|ARM64.Build.0 = Release|ARM64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|x64.ActiveCfg = Release|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|x64.Build.0 = Release|x64 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|x86.ActiveCfg = Release|Win32 + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}.Release|x86.Build.0 = Release|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|ARM64.Build.0 = Debug|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|x64.ActiveCfg = Debug|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|x64.Build.0 = Debug|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|x86.ActiveCfg = Debug|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Debug|x86.Build.0 = Debug|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|ARM64.ActiveCfg = Release|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|ARM64.Build.0 = Release|ARM64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x64.ActiveCfg = Release|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x64.Build.0 = Release|x64 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x86.ActiveCfg = Release|Win32 + {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5012,7 +5012,7 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} @@ -5040,8 +5040,8 @@ Global {AC215730-2B5F-4498-B7F5-5DB80AEFCA5F} = {278D8859-20B1-428F-8448-064F46E1F021} {0835E6BF-0170-4E99-A55C-E06E1EF4C3B2} = {278D8859-20B1-428F-8448-064F46E1F021} {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {278D8859-20B1-428F-8448-064F46E1F021} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {9DE2FC01-A839-4F89-8319-9071D4C54821} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From ed8c4c1b9b0154a84746c9316a58023d7d351ff2 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 17:01:38 +0200 Subject: [PATCH 039/102] REXM: Update examples collection, some renames --- examples/Makefile | 6 +- examples/Makefile.Web | 18 ++-- examples/README.md | 12 +-- examples/core/core_highdpi_testbed.c | 6 +- ...nitor_change.c => core_monitor_detector.c} | 14 +-- ...r_change.png => core_monitor_detector.png} | Bin examples/core/core_screen_recording.c | 6 +- examples/examples_list.txt | 20 ++--- examples/shapes/shapes_pie_chart.c | 2 +- examples/shapes/shapes_simple_particles.c | 34 ++++--- ..._starfield.c => shapes_starfield_effect.c} | 83 +++++++++--------- ...rfield.png => shapes_starfield_effect.png} | Bin ....vcxproj => core_monitor_detector.vcxproj} | 6 +- ...cxproj => shapes_starfield_effect.vcxproj} | 6 +- projects/VS2022/raylib.sln | 4 +- tools/rexm/examples_report.md | 18 ++-- tools/rexm/examples_report_issues.md | 2 + 17 files changed, 126 insertions(+), 111 deletions(-) rename examples/core/{core_monitor_change.c => core_monitor_detector.c} (96%) rename examples/core/{core_monitor_change.png => core_monitor_detector.png} (100%) rename examples/shapes/{shapes_starfield.c => shapes_starfield_effect.c} (66%) rename examples/shapes/{shapes_starfield.png => shapes_starfield_effect.png} (100%) rename projects/VS2022/examples/{core_monitor_change.vcxproj => core_monitor_detector.vcxproj} (99%) rename projects/VS2022/examples/{shapes_starfield.vcxproj => shapes_starfield_effect.vcxproj} (99%) diff --git a/examples/Makefile b/examples/Makefile index 498a36f47..30d619e94 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -529,7 +529,7 @@ CORE = \ core/core_input_mouse_wheel \ core/core_input_multitouch \ core/core_input_virtual_controls \ - core/core_monitor_change \ + core/core_monitor_detector \ core/core_random_sequence \ core/core_random_values \ core/core_render_texture \ @@ -572,7 +572,7 @@ SHAPES = \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ - shapes/shapes_starfield \ + shapes/shapes_starfield_effect \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle @@ -632,7 +632,6 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ @@ -643,6 +642,7 @@ MODELS = \ models/models_orthographic_projection \ models/models_point_rendering \ models/models_rlgl_solar_system \ + models/models_rotating_cube \ models/models_skybox_rendering \ models/models_tesseract_view \ models/models_textured_cube \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 1b32ebddf..222c56e11 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -529,7 +529,7 @@ CORE = \ core/core_input_mouse_wheel \ core/core_input_multitouch \ core/core_input_virtual_controls \ - core/core_monitor_change \ + core/core_monitor_detector \ core/core_random_sequence \ core/core_random_values \ core/core_render_texture \ @@ -572,7 +572,7 @@ SHAPES = \ shapes/shapes_rounded_rectangle_drawing \ shapes/shapes_simple_particles \ shapes/shapes_splines_drawing \ - shapes/shapes_starfield \ + shapes/shapes_starfield_effect \ shapes/shapes_top_down_lights \ shapes/shapes_triangle_strip \ shapes/shapes_vector_angle @@ -632,7 +632,6 @@ MODELS = \ models/models_cubicmap_rendering \ models/models_first_person_maze \ models/models_geometric_shapes \ - models/models_rotating_cube \ models/models_heightmap_rendering \ models/models_loading \ models/models_loading_gltf \ @@ -643,6 +642,7 @@ MODELS = \ models/models_orthographic_projection \ models/models_point_rendering \ models/models_rlgl_solar_system \ + models/models_rotating_cube \ models/models_skybox_rendering \ models/models_tesseract_view \ models/models_textured_cube \ @@ -795,7 +795,7 @@ core/core_input_multitouch: core/core_input_multitouch.c core/core_input_virtual_controls: core/core_input_virtual_controls.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -core/core_monitor_change: core/core_monitor_change.c +core/core_monitor_detector: core/core_monitor_detector.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) core/core_random_sequence: core/core_random_sequence.c @@ -920,7 +920,7 @@ shapes/shapes_simple_particles: shapes/shapes_simple_particles.c shapes/shapes_splines_drawing: shapes/shapes_splines_drawing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) -shapes/shapes_starfield: shapes/shapes_starfield.c +shapes/shapes_starfield_effect: shapes/shapes_starfield_effect.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) shapes/shapes_top_down_lights: shapes/shapes_top_down_lights.c @@ -1154,10 +1154,6 @@ 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_rotating_cube: models/models_rotating_cube.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ - --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png - models/models_heightmap_rendering: models/models_heightmap_rendering.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/heightmap.png@resources/heightmap.png @@ -1201,6 +1197,10 @@ models/models_point_rendering: models/models_point_rendering.c models/models_rlgl_solar_system: models/models_rlgl_solar_system.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +models/models_rotating_cube: models/models_rotating_cube.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png + models/models_skybox_rendering: models/models_skybox_rendering.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/shaders/glsl100/skybox.vs@resources/shaders/glsl100/skybox.vs \ diff --git a/examples/README.md b/examples/README.md index dbc36fe22..b40966a5a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -49,7 +49,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_window_flags](core/core_window_flags.c) | core_window_flags | ⭐⭐⭐☆ | 3.5 | 3.5 | [Ramon Santamaria](https://github.com/raysan5) | | [core_window_letterbox](core/core_window_letterbox.c) | core_window_letterbox | ⭐⭐☆☆ | 2.5 | 4.0 | [Anata](https://github.com/anatagawa) | | [core_window_should_close](core/core_window_should_close.c) | core_window_should_close | ⭐☆☆☆ | 4.2 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | -| [core_monitor_change](core/core_monitor_change.c) | core_monitor_change | ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) | +| [core_monitor_detector](core/core_monitor_detector.c) | core_monitor_detector | ⭐☆☆☆ | 5.5 | 5.6 | [Maicon Santana](https://github.com/maiconpintoabreu) | | [core_custom_logging](core/core_custom_logging.c) | core_custom_logging | ⭐⭐⭐☆ | 2.5 | 2.5 | [Pablo Marcos Oltra](https://github.com/pamarcos) | | [core_drop_files](core/core_drop_files.c) | core_drop_files | ⭐⭐☆☆ | 1.3 | 4.2 | [Ramon Santamaria](https://github.com/raysan5) | | [core_random_values](core/core_random_values.c) | core_random_values | ⭐☆☆☆ | 1.1 | 1.1 | [Ramon Santamaria](https://github.com/raysan5) | @@ -66,8 +66,8 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_undo_redo](core/core_undo_redo.c) | core_undo_redo | ⭐⭐⭐☆ | 5.5 | 5.6 | [Ramon Santamaria](https://github.com/raysan5) | | [core_input_actions](core/core_input_actions.c) | core_input_actions | ⭐⭐☆☆ | 5.5 | 5.6 | [Jett](https://github.com/JettMonstersGoBoom) | | [core_directory_files](core/core_directory_files.c) | core_directory_files | ⭐☆☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | -| [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | -| [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.5 | 5.6 | [](https://github.com/) | +| [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | +| [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | ### category: shapes [31] @@ -101,12 +101,12 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_dashed_line](shapes/shapes_dashed_line.c) | shapes_dashed_line | ⭐☆☆☆ | 5.5 | 5.5 | [Luís Almeida](https://github.com/luis605) | | [shapes_triangle_strip](shapes/shapes_triangle_strip.c) | shapes_triangle_strip | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | | [shapes_vector_angle](shapes/shapes_vector_angle.c) | shapes_vector_angle | ⭐⭐☆☆ | 1.0 | 5.0 | [Ramon Santamaria](https://github.com/raysan5) | -| [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐☆☆☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | +| [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | shapes_kaleidoscope | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | shapes_clock_of_clocks | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | | [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [[Balamurugan R]](https://github.com/[Bala050814]) | -| [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐☆☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | -| [shapes_starfield](shapes/shapes_starfield.c) | shapes_starfield | ⭐☆☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | +| [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | shapes_starfield_effect | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: textures [26] diff --git a/examples/core/core_highdpi_testbed.c b/examples/core/core_highdpi_testbed.c index b22aa507a..5cd2a7dc7 100644 --- a/examples/core/core_highdpi_testbed.c +++ b/examples/core/core_highdpi_testbed.c @@ -4,14 +4,14 @@ * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * -* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Ramon Santamaria (@raysan5) 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) 0 (@) +* Copyright (c) 2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/core/core_monitor_change.c b/examples/core/core_monitor_detector.c similarity index 96% rename from examples/core/core_monitor_change.c rename to examples/core/core_monitor_detector.c index 3286ba22d..0e94f6895 100644 --- a/examples/core/core_monitor_change.c +++ b/examples/core/core_monitor_detector.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [core] example - monitor change +* raylib [core] example - monitor detector * * Example complexity rating: [★☆☆☆] 1/4 * @@ -19,8 +19,8 @@ #define MAX_MONITORS 10 -// Monitor Details -typedef struct Monitor { +// Monitor info +typedef struct MonitorInfo { Vector2 position; const char *name; int width; @@ -28,7 +28,7 @@ typedef struct Monitor { int physicalWidth; int physicalHeight; int refreshRate; -} Monitor; +} MonitorInfo; //------------------------------------------------------------------------------------ // Program main entry point @@ -40,9 +40,9 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - Monitor monitors[MAX_MONITORS] = { 0 }; + MonitorInfo monitors[MAX_MONITORS] = { 0 }; - InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor change"); + InitWindow(screenWidth, screenHeight, "raylib [core] example - monitor detector"); int currentMonitorIndex = GetCurrentMonitor(); int monitorCount = 0; @@ -67,7 +67,7 @@ int main(void) monitorCount = GetMonitorCount(); for (int i = 0; i < monitorCount; i++) { - monitors[i] = (Monitor){ + monitors[i] = (MonitorInfo){ GetMonitorPosition(i), GetMonitorName(i), GetMonitorWidth(i), diff --git a/examples/core/core_monitor_change.png b/examples/core/core_monitor_detector.png similarity index 100% rename from examples/core/core_monitor_change.png rename to examples/core/core_monitor_detector.png diff --git a/examples/core/core_screen_recording.c b/examples/core/core_screen_recording.c index 9d0611bde..43c90eec5 100644 --- a/examples/core/core_screen_recording.c +++ b/examples/core/core_screen_recording.c @@ -4,14 +4,14 @@ * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * -* Example contributed by (@) and reviewed by Ramon Santamaria (@raysan5) +* Example contributed by Ramon Santamaria (@raysan5) 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) 0 (@) +* Copyright (c) 2025 Ramon Santamaria (@raysan5) * ********************************************************************************************/ diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 7abfdd453..6c9d0c3bd 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -31,7 +31,7 @@ core;core_world_screen;★★☆☆;1.3;1.4;2015;2025;"Ramon Santamaria";@raysan core;core_window_flags;★★★☆;3.5;3.5;2020;2025;"Ramon Santamaria";@raysan5 core;core_window_letterbox;★★☆☆;2.5;4.0;2019;2025;"Anata";@anatagawa core;core_window_should_close;★☆☆☆;4.2;4.2;2013;2025;"Ramon Santamaria";@raysan5 -core;core_monitor_change;★☆☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu +core;core_monitor_detector;★☆☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu core;core_custom_logging;★★★☆;2.5;2.5;2018;2025;"Pablo Marcos Oltra";@pamarcos core;core_drop_files;★★☆☆;1.3;4.2;2015;2025;"Ramon Santamaria";@raysan5 core;core_random_values;★☆☆☆;1.1;1.1;2014;2025;"Ramon Santamaria";@raysan5 @@ -48,8 +48,9 @@ core;core_render_texture;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamari core;core_undo_redo;★★★☆;5.5;5.6;2025;2025;"Ramon Santamaria";@raysan5 core;core_input_actions;★★☆☆;5.5;5.6;2025;2025;"Jett";@JettMonstersGoBoom core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal -core;core_highdpi_testbed;★☆☆☆;5.5;5.6;0;0;"";@ -core;core_screen_recording;★☆☆☆;5.5;5.6;0;0;"";@ +core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 +core;core_screen_recording;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 +core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower @@ -75,7 +76,12 @@ shapes;shapes_double_pendulum;★★☆☆;5.5;5.5;2025;2025;"JoeCheong";@Joeche shapes;shapes_dashed_line;★☆☆☆;5.5;5.5;2025;2025;"Luís Almeida";@luis605 shapes;shapes_triangle_strip;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@raysan5 -shapes;shapes_pie_chart;★☆☆☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf +shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf +shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal +shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates +shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] +shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant +shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 @@ -186,9 +192,3 @@ others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flas others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5 -shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal -core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary -shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates -shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] -shapes;shapes_simple_particles;★☆☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant -shapes;shapes_starfield;★☆☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates diff --git a/examples/shapes/shapes_pie_chart.c b/examples/shapes/shapes_pie_chart.c index e2f6900eb..566e3a4d1 100644 --- a/examples/shapes/shapes_pie_chart.c +++ b/examples/shapes/shapes_pie_chart.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - pie chart * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★★☆] 3/4 * * Example originally created with raylib 5.5, last time updated with raylib 5.6 * diff --git a/examples/shapes/shapes_simple_particles.c b/examples/shapes/shapes_simple_particles.c index 5bef0917a..7c2a598c2 100644 --- a/examples/shapes/shapes_simple_particles.c +++ b/examples/shapes/shapes_simple_particles.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - simple particles * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 5.6, last time updated with raylib 5.6 * @@ -20,7 +20,7 @@ #include // Required for: calloc(), free() #include // Required for: cosf(), sinf() -#define MAX_PARTICLES 3000 // Max number particles +#define MAX_PARTICLES 3000 // Max number of particles //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -100,6 +100,7 @@ int main(void) // Update the parameters of each particle UpdateParticles(&circularBuffer, screenWidth, screenHeight); + // Remove dead particles from the circular buffer UpdateCircularBuffer(&circularBuffer); @@ -217,46 +218,53 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int switch (circularBuffer->buffer[i].type) { case WATER: + { circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; circularBuffer->buffer[i].velocity.y += 0.2f; // Gravity circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; - break; + } break; case SMOKE: + { circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x; circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].radius += 0.5f; // Increment radius: smoke expands circularBuffer->buffer[i].color.a -= 4; // Decrement alpha: smoke fades - if (circularBuffer->buffer[i].color.a < 4) // If alpha transparent, particle dies - circularBuffer->buffer[i].alive = false; - break; + + // If alpha transparent, particle dies + if (circularBuffer->buffer[i].color.a < 4) circularBuffer->buffer[i].alive = false; + } break; case FIRE: + { // Add a little horizontal oscillation to fire particles circularBuffer->buffer[i].position.x += circularBuffer->buffer[i].velocity.x + cosf(circularBuffer->buffer[i].lifeTime*215.0f); circularBuffer->buffer[i].velocity.y -= 0.05f; // Upwards circularBuffer->buffer[i].position.y += circularBuffer->buffer[i].velocity.y; circularBuffer->buffer[i].radius -= 0.15f; // Decrement radius: fire shrinks circularBuffer->buffer[i].color.g -= 3; // Decrement green: fire turns reddish starting from yellow - if (circularBuffer->buffer[i].radius <= 0.02f) // If radius too small, particle dies - circularBuffer->buffer[i].alive = false; - break; + + // If radius too small, particle dies + if (circularBuffer->buffer[i].radius <= 0.02f) circularBuffer->buffer[i].alive = false; + } break; default: break; } // Disable particle when out of screen Vector2 center = circularBuffer->buffer[i].position; float radius = circularBuffer->buffer[i].radius; - if ((center.x < -radius) || (center.x > screenWidth + radius) || - (center.y < -radius) || (center.y > screenHeight + radius)) + + if ((center.x < -radius) || (center.x > (screenWidth + radius)) || + (center.y < -radius) || (center.y > (screenHeight + radius))) + { circularBuffer->buffer[i].alive = false; + } } } static void UpdateCircularBuffer(CircularBuffer *circularBuffer) { // Update circular buffer: advance tail over dead particles - while ((circularBuffer->tail != circularBuffer->head) && - !circularBuffer->buffer[circularBuffer->tail].alive) + while ((circularBuffer->tail != circularBuffer->head) && !circularBuffer->buffer[circularBuffer->tail].alive) { circularBuffer->tail = (circularBuffer->tail + 1)%MAX_PARTICLES; } diff --git a/examples/shapes/shapes_starfield.c b/examples/shapes/shapes_starfield_effect.c similarity index 66% rename from examples/shapes/shapes_starfield.c rename to examples/shapes/shapes_starfield_effect.c index df543d066..8dd90fe0b 100644 --- a/examples/shapes/shapes_starfield.c +++ b/examples/shapes/shapes_starfield_effect.c @@ -1,8 +1,8 @@ /******************************************************************************************* * -* raylib [shapes] example - starfield +* raylib [shapes] example - starfield effect * -* Example complexity rating: [★☆☆☆] 1/4 +* Example complexity rating: [★★☆☆] 2/4 * * Example originally created with raylib 5.5, last time updated with raylib 5.6-dev * @@ -31,7 +31,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield effect"); Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.69f); @@ -45,9 +45,10 @@ int main(void) Vector2 starsScreenPos[STAR_COUNT] = { 0 }; // Setup the stars with a random position - for (int i = 0; i < STAR_COUNT; i++) { - stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); - stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + for (int i = 0; i < STAR_COUNT; i++) + { + stars[i].x = GetRandomValue(-screenWidth*0.5f, screenWidth*0.5f); + stars[i].y = GetRandomValue(-screenHeight*0.5f, screenHeight*0.5f); stars[i].z = 1.0f; } @@ -59,39 +60,36 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - - // Change speed based on number keys - for (int i = 0; i <= 9; i++) { - if (IsKeyPressed(KEY_ZERO + i)) { - speed = 2.0f * (float)i / 9.0f; - } - } + // Change speed based on mouse + float mouseMove = GetMouseWheelMove(); + if ((int)mouseMove != 0) speed += 2.0f*mouseMove/9.0f; + if (speed < 0.0f) speed = 0.1f; + else if (speed > 2.0f) speed = 2.0f; // Toggle lines / points with space bar - if (IsKeyPressed(KEY_SPACE)) { - drawLines = !drawLines; - } + if (IsKeyPressed(KEY_SPACE)) drawLines = !drawLines; float dt = GetFrameTime(); - for (int i = 0; i < STAR_COUNT; i++) { + for (int i = 0; i < STAR_COUNT; i++) + { // Update star's timer - stars[i].z -= dt * speed; + stars[i].z -= dt*speed; + // Calculate the screen position - starsScreenPos[i] = (Vector2) { - screenWidth*.5f + stars[i].x / stars[i].z, - screenHeight*.5f + stars[i].y / stars[i].z, + starsScreenPos[i] = (Vector2){ + screenWidth*0.5f + stars[i].x/stars[i].z, + screenHeight*0.5f + stars[i].y/stars[i].z, }; + // If the star is too old, or offscreen, it dies and we make a new random one - if (stars[i].z < 0.0f - || starsScreenPos[i].x < 0 || starsScreenPos[i].y < 0.0f - || starsScreenPos[i].x > screenWidth || starsScreenPos[i].y > screenHeight) { - stars[i].x = GetRandomValue(-screenWidth*.5, screenWidth*.5); - stars[i].y = GetRandomValue(-screenHeight*.5, screenHeight*.5); + if ((stars[i].z < 0.0f) || (starsScreenPos[i].x < 0) || (starsScreenPos[i].y < 0.0f) || + (starsScreenPos[i].x > screenWidth) || (starsScreenPos[i].y > screenHeight)) + { + stars[i].x = GetRandomValue(-screenWidth*0.5f, screenWidth*0.5f); + stars[i].y = GetRandomValue(-screenHeight*0.5f, screenHeight*0.5f); stars[i].z = 1.0f; } } - - //---------------------------------------------------------------------------------- // Draw @@ -100,42 +98,47 @@ int main(void) ClearBackground(bgColor); - for (int i = 0; i < STAR_COUNT; i++) { - if (drawLines) { + for (int i = 0; i < STAR_COUNT; i++) + { + if (drawLines) + { // Get the time a little while ago for this star, but clamp it float t = Clamp(stars[i].z + 1.0f/32.0f, 0.0f, 1.0f); + // If it's different enough from the current time, we proceed - if (t - stars[i].z > 1e-3) { + if ((t - stars[i].z) > 1e-3) + { // Calculate the screen position of the old point - Vector2 startPos = (Vector2) { - screenWidth*.5f + stars[i].x / t, - screenHeight*.5f + stars[i].y / t, + Vector2 startPos = (Vector2){ + screenWidth*0.5f + stars[i].x/t, + screenHeight*0.5f + stars[i].y/t, }; + // Draw a line connecting the old point to the current point DrawLineV(startPos, starsScreenPos[i], RAYWHITE); } } - else { + else + { // Make the radius grow as the star ages float radius = Lerp(stars[i].z, 1.0f, 5.0f); + // Draw the circle DrawCircleV(starsScreenPos[i], radius, RAYWHITE); } } + DrawText(TextFormat("[MOUSE WHEEL] Current Speed: %.0f", 9.0f*speed/2.0f), 10, 40, 20, RAYWHITE); + DrawText(TextFormat("[SPACE] Current draw mode: %s", drawLines ? "Lines" : "Circles"), 10, 70, 20, RAYWHITE); + DrawFPS(10, 10); - DrawText(TextFormat("Current Speed: %.0f [Number keys to change]", 9.0f * speed / 2.0f), 10, 30, 20, RAYWHITE); - DrawText(TextFormat("Drawing %s [Space to change]", drawLines ? "Lines" : "Circles"), 10, 50, 20, RAYWHITE); - - EndDrawing(); //---------------------------------------------------------------------------------- } // De-Initialization //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/shapes/shapes_starfield.png b/examples/shapes/shapes_starfield_effect.png similarity index 100% rename from examples/shapes/shapes_starfield.png rename to examples/shapes/shapes_starfield_effect.png diff --git a/projects/VS2022/examples/core_monitor_change.vcxproj b/projects/VS2022/examples/core_monitor_detector.vcxproj similarity index 99% rename from projects/VS2022/examples/core_monitor_change.vcxproj rename to projects/VS2022/examples/core_monitor_detector.vcxproj index 07921bef3..bafb1b15c 100644 --- a/projects/VS2022/examples/core_monitor_change.vcxproj +++ b/projects/VS2022/examples/core_monitor_detector.vcxproj @@ -53,9 +53,9 @@ {FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3} Win32Proj - core_monitor_change + core_monitor_detector 10.0 - core_monitor_change + core_monitor_detector @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/examples/shapes_starfield.vcxproj b/projects/VS2022/examples/shapes_starfield_effect.vcxproj similarity index 99% rename from projects/VS2022/examples/shapes_starfield.vcxproj rename to projects/VS2022/examples/shapes_starfield_effect.vcxproj index 5cfc0a6d3..794ec633e 100644 --- a/projects/VS2022/examples/shapes_starfield.vcxproj +++ b/projects/VS2022/examples/shapes_starfield_effect.vcxproj @@ -53,9 +53,9 @@ {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} Win32Proj - shapes_starfield + shapes_starfield_effect 10.0 - shapes_starfield + shapes_starfield_effect @@ -553,7 +553,7 @@ - + diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index be06d43a2..c4de89730 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -361,7 +361,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_rotating_cube", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_ascii_rendering", "examples\shaders_ascii_rendering.vcxproj", "{5F4B766F-DD52-4B53-B6C3-BC7611E17F20}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_change", "examples\core_monitor_change.vcxproj", "{FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_monitor_detector", "examples\core_monitor_detector.vcxproj", "{FF5F9EE9-29C5-40EE-BBCF-AE51B001FEC3}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "web_basic_window", "examples\web_basic_window.vcxproj", "{A9C422E7-0F03-4DBC-AC93-5C3EF4942DEC}" EndProject @@ -385,7 +385,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_clock_of_clocks", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_mouse_trail", "examples\shapes_mouse_trail.vcxproj", "{0835E6BF-0170-4E99-A55C-E06E1EF4C3B2}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield", "examples\shapes_starfield.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_starfield_effect", "examples\shapes_starfield_effect.vcxproj", "{EA4AD5A7-DB95-43C0-9A67-2D94146BCF91}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "examples\core_highdpi_testbed.vcxproj", "{1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F}" EndProject diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index e55610a30..e058e09a7 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -44,7 +44,7 @@ Example elements validated: | core_window_flags | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_window_letterbox | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_window_should_close | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| core_monitor_change | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_monitor_detector | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_custom_logging | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_drop_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_random_values | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -61,6 +61,9 @@ Example elements validated: | core_undo_redo | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_input_actions | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_directory_files | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_highdpi_testbed | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_screen_recording | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bullet_hell | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -87,6 +90,11 @@ Example elements validated: | shapes_triangle_strip | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_vector_angle | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_pie_chart | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_starfield_effect | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -152,7 +160,7 @@ Example elements validated: | models_bone_socket | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_tesseract_view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_basic_voxel | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| models_geometry_textures_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| models_rotating_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_ascii_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_basic_lighting | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_model_shader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -197,9 +205,3 @@ Example elements validated: | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_starfield | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | diff --git a/tools/rexm/examples_report_issues.md b/tools/rexm/examples_report_issues.md index 5178dabdd..3136c2709 100644 --- a/tools/rexm/examples_report_issues.md +++ b/tools/rexm/examples_report_issues.md @@ -20,6 +20,8 @@ Example elements validated: ``` | **EXAMPLE NAME** | [C] | [CAT]| [INFO]|[PNG]|[WPNG]| [RES]| [MK] |[MKWEB]| [VCX]| [SOL]|[RDME]|[JS] | [WOUT]|[WMETA]| |:---------------------------------|:---:|:----:|:-----:|:---:|:----:|:----:|:----:|:-----:|:----:|:----:|:----:|:---:|:-----:|:-----:| +| core_highdpi_testbed | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_screen_recording | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | rlgl_standalone | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | rlgl_compute_shader | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From 7995f8d1b3a436d5e000dbda9113b8b8a25a1f21 Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 17:01:58 +0200 Subject: [PATCH 040/102] Avoid auto push on rename --- tools/rexm/rexm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index c615e810f..20fc1d5e5 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -69,7 +69,7 @@ #define REXM_MAX_RESOURCE_PATHS 256 // Create local commit with changes on example renaming -#define RENAME_AUTO_COMMIT_CREATION +//#define RENAME_AUTO_COMMIT_CREATION //---------------------------------------------------------------------------------- // Types and Structures Definition From cd0d693a5685aa9a6d5b4c8a910679c09bd4a35a Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 17:09:55 +0200 Subject: [PATCH 041/102] Reviewed example --- examples/examples_list.txt | 2 +- examples/shapes/shapes_mouse_trail.c | 26 +++++++++++--------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 6c9d0c3bd..9989f940f 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -79,7 +79,7 @@ shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@ra shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates -shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2024;2024;"[Balamurugan R]";@[Bala050814] +shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814 shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/shapes/shapes_mouse_trail.c b/examples/shapes/shapes_mouse_trail.c index ad1166548..e0e5a3c1d 100644 --- a/examples/shapes/shapes_mouse_trail.c +++ b/examples/shapes/shapes_mouse_trail.c @@ -6,16 +6,17 @@ * * Example originally created with raylib 5.6 * -* Example contributed by [Balamurugan R] (@[Bala050814]]) and reviewed by [Ray] (@raysan5) +* Example contributed by Balamurugan R (@Bala050814]) 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 [Balamurugan R] (@[Bala050814]) +* Copyright (c) 2025 Balamurugan R (@Bala050814) * ********************************************************************************************/ #include "raylib.h" + #include "raymath.h" // Define the maximum number of positions to store in the trail @@ -46,14 +47,14 @@ int main(void) //---------------------------------------------------------------------------------- Vector2 mousePosition = GetMousePosition(); - // 1. Shift all existing positions backward by one slot in the array - // The last element (the oldest position) is dropped. + // Shift all existing positions backward by one slot in the array + // The last element (the oldest position) is dropped for (int i = MAX_TRAIL_LENGTH - 1; i > 0; i--) { trailPositions[i] = trailPositions[i - 1]; } - // 2. Store the new, current mouse position at the start of the array (Index 0) + // Store the new, current mouse position at the start of the array (Index 0) trailPositions[0] = mousePosition; //---------------------------------------------------------------------------------- @@ -61,24 +62,23 @@ int main(void) //---------------------------------------------------------------------------------- BeginDrawing(); - // Use BLACK for a darker background to make the colored trail pop ClearBackground(BLACK); - // 3. Draw the trail by looping through the history array + // Draw the trail by looping through the history array for (int i = 0; i < MAX_TRAIL_LENGTH; i++) { // Ensure we skip drawing if the array hasn't been fully filled on startup - if (trailPositions[i].x != 0.0f || trailPositions[i].y != 0.0f) + if ((trailPositions[i].x != 0.0f) || (trailPositions[i].y != 0.0f)) { // Calculate relative trail strength (ratio is near 1.0 for new, near 0.0 for old) float ratio = (float)(MAX_TRAIL_LENGTH - i) / MAX_TRAIL_LENGTH; // Fade effect: oldest positions are more transparent // Fade (color, alpha) - alpha is 0.5 to 1.0 based on ratio - Color trailColor = Fade(SKYBLUE, ratio * 0.5f + 0.5f); + Color trailColor = Fade(SKYBLUE, ratio*0.5f + 0.5f); // Size effect: oldest positions are smaller - float trailRadius = 15.0f * ratio; + float trailRadius = 15.0f*ratio; DrawCircleV(trailPositions[i], trailRadius, trailColor); } @@ -87,8 +87,7 @@ int main(void) // Draw a distinct white circle for the current mouse position (Index 0) DrawCircleV(mousePosition, 15.0f, WHITE); - DrawText("Move the mouse to see the trail effect!", - 10, screenHeight - 30, 20, LIGHTGRAY); + DrawText("Move the mouse to see the trail effect!", 10, screenHeight - 30, 20, LIGHTGRAY); EndDrawing(); //---------------------------------------------------------------------------------- @@ -96,9 +95,6 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - - // No resources loaded, nothing to unload. - CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- From ab4831911ab8568cea2ee4d14acfb5ff2847cce8 Mon Sep 17 00:00:00 2001 From: Aanjishnu Bhattacharyya <71861112+NimComPoo-04@users.noreply.github.com> Date: Fri, 17 Oct 2025 20:42:14 +0530 Subject: [PATCH 042/102] [examples] Added: `core_text_file_loading` (#5278) Added and example demonstrating reading the contents of a file and rendering them, utilizing rtext module. The demonstration also handles wrapping of long sentences, and text scrolling. Co-authored-by: Ray --- examples/Makefile | 1 + examples/Makefile.Web | 5 + examples/core/core_text_file_loading.c | 164 +++++ examples/core/core_text_file_loading.png | Bin 0 -> 23575 bytes examples/core/resources/text_file.txt | 18 + .../examples/core_text_file_loading.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 2 + 7 files changed, 759 insertions(+) create mode 100644 examples/core/core_text_file_loading.c create mode 100644 examples/core/core_text_file_loading.png create mode 100644 examples/core/resources/text_file.txt create mode 100644 projects/VS2022/examples/core_text_file_loading.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 30d619e94..a9732679d 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -537,6 +537,7 @@ CORE = \ core/core_screen_recording \ core/core_smooth_pixelperfect \ core/core_storage_values \ + core/core_text_file_loading \ core/core_undo_redo \ core/core_vr_simulator \ core/core_window_flags \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 222c56e11..88843af09 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -537,6 +537,7 @@ CORE = \ core/core_screen_recording \ core/core_smooth_pixelperfect \ core/core_storage_values \ + core/core_text_file_loading \ core/core_undo_redo \ core/core_vr_simulator \ core/core_window_flags \ @@ -819,6 +820,10 @@ core/core_smooth_pixelperfect: core/core_smooth_pixelperfect.c core/core_storage_values: core/core_storage_values.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +core/core_text_file_loading: core/core_text_file_loading.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file core/resources/text_file.txt@resources/text_file.txt + core/core_undo_redo: core/core_undo_redo.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/core/core_text_file_loading.c b/examples/core/core_text_file_loading.c new file mode 100644 index 000000000..0077551fd --- /dev/null +++ b/examples/core/core_text_file_loading.c @@ -0,0 +1,164 @@ +/******************************************************************************************* +* +* raylib [core] example - text file loading +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* +* Example contributed by Aanjishnu Bhattacharyya (@NimComPoo-04) 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) 0 Aanjishnu Bhattacharyya (@NimComPoo-04) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" // For Lerp + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - text file loading"); + + // Setting up the camera + Camera2D cam = { + .offset = {0, 0}, + .target = {0, 0}, + .rotation = 0, + .zoom = 1 + }; + + // Loading file from resources/text_file.txt + const char *fileName = "resources/text_file.txt"; + char *fileData = LoadFileText(fileName); + + // Loading all the lines + int lineCount = 0; + char **lines = LoadTextLines(fileData, &lineCount); + + // Just sylistic choise + int fontSize = 20; + int textTop = 25 + fontSize; // Top of the screen from where the text is rendered + int wrapWidth = screenWidth - 20; + + // Wrap the lines as needed + for(int i = 0; i < lineCount; i++) + { + int j = 0; + int lastSpace = 0; // Keeping track of last valid space to insert '\n' + int lastWrapStart = 0; // Keeping track of the start of this wrapped line. + + while(lines[i][j] != '\0') + { + if(lines[i][j] == ' ') + { + // Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function + lines[i][j] = '\0'; + + // Checking if the text has crossed the wrapWidth, then going back and inserting a newline + if(MeasureText(lines[i] + lastWrapStart, fontSize) > wrapWidth) + { + lines[i][lastSpace] = '\n'; + + // Since we added a newline the place of wrap changed so we update our lastWrapStart + lastWrapStart = lastSpace + 1; + } + + lines[i][j] = ' '; // Resetting the space back + lastSpace = j; // Since we encountered a new space we update our last encountered space location + } + + j++; + } + } + + // Calculating the total height so that we can show a scrollbar + int textHeight = 0; + + for(int i = 0; i < lineCount; i++) + { + Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); + textHeight += size.y + 10; + } + + // A simple scrollbar on the side to show how far we have red into the file + Rectangle scrollBar = { + .x = screenWidth - 5, + .y = 0, + .width = 5, + .height = screenHeight * 100 / (textHeight - screenHeight) // Scrollbar height is just a percentage + }; + + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + float scroll = GetMouseWheelMove(); + cam.target.y -= scroll * fontSize * 1.5; // Choosing an arbitrary speed for scroll + + if(cam.target.y < 0) // Snapping to 0 if we go too far back + cam.target.y = 0; + + if(cam.target.y > textHeight - screenHeight + textTop) // Ensuring that the camera does not scroll past all text + cam.target.y = textHeight - screenHeight + textTop; + + // Computing the position of the scrollBar depending on the percentage of text covered. + scrollBar.y = Lerp(textTop, screenHeight - scrollBar.height, (cam.target.y - textTop) / (textHeight - screenHeight)); + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode2D(cam); + + Font defaultFont = GetFontDefault(); + + // Going through all the read lines + for(int i = 0, t = textTop; i < lineCount; i++) + { + // Each time we go through and calculate the height of the text to move the cursor appropriately + Vector2 size = MeasureTextEx(defaultFont, lines[i], fontSize, 2); + DrawText(lines[i], 10, t, fontSize, RED); + + // Inserting extra space for real newlines, wrapped lines are rendered closer together + t += size.y + 10; + } + EndMode2D(); + + // Header displaying which file is being read currently + DrawRectangle(0, 0, screenWidth, textTop - 10, BEIGE); + DrawText(TextFormat("File: %s", fileName), 10, 10, fontSize, MAROON); + + DrawRectangleRec(scrollBar, MAROON); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadTextLines(lines, lineCount); + UnloadFileText(fileData); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/core/core_text_file_loading.png b/examples/core/core_text_file_loading.png new file mode 100644 index 0000000000000000000000000000000000000000..ac4101210a2229e059f49e71aa3496e3f072a361 GIT binary patch literal 23575 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 z zbc=;EmW1}t4=HB1+H>)6=anCdrpE)c|7rHdCtVia_|W;K2jAAq%6gwY&gy^pCcgGF z^V&U&}zww`h@BJIj4N)JB0$x^cxg+g+6C46y;xM!+g?BUUi)sf4<)R-k ztk&@}E)}=ApAVP6am7C7aJ@-v@3d85b5IBiCvfXQ6=mfUa&>V*m&Icr=iCb(Mmft^ zmi1jY!+B=;i&q!lDweUa-L3mFVab)+mZY|r|3XI7Z$0GP%pYDcAxnN&<&j_Qw;pz$ zwuyPkWV`RgTusFkzLhVVt_UTV+;w*93E1hlcBVnp^WvDFoYVgo{OrE=RQ52+!HkSX z5Qp6aM>;kF)U0`tD!fq8%IV#L5c{3aCQI8b*){#f#7L)C9kMf3uf`ww)gJb4ap)gm z>33JW?6>$GztVNR(eL|?ONMJdT}?Rs+~9kFcI~3y{bA4guH8ir6$j|H!^wDS5@Urc zQO5Q+9?iIL=3s)P;gYL7>{}l-hrN@2^H0s}58G_}6?5NZzTLl2tgd;hp0w7}yBX22 zxidHCgo?HUpw8JTS>kRc@ZThr1 zSJx)ziEyo2%Z(q)Lw^LHuKO}EHtBEY>G&mmIl|d|3ky`P$?y1Me&e#O-v5hMvI}PW z=lz-VsxE4!y1C5Bv&WaTUC)rUlR`SC@dqRpYq3QjSnLAy9F6%Bw@=7g%J+I-5s=_L zeo@3wim3&(Otxp)BoycGgS5v{_TM0dstF6|Ft5dlzIO!{e7)Cy@rM*|<3jI@$e06mCU$~hDa18x;PA#qfEGs+YWh$-US>t;(7d6)+zvFR z#l6w2)}&C$OY{HC+Qk>$j|w!j{?6EO$t-eVyYa?{ez~PjehE#telfSs?Xq_1rI!J` z?n$pXBQy@4+InzOU3=71(~!fxQ7@}EOxge9Wn0Mq-f5R_6wB?sd@|$lRA{Ptge?le zVxUyD*&r|YC@eam?DcAgtCQ zt0qX>HZV(n=gY236T_Uo%K6L-`?ol(W@6O3fYpDLugg^Jo__7=y9Dm~sOij8riCAA z6JPq2=`eBURT#w_s@m{MTgg0f3-NJE_kbMe$DOm!;3Qh{Q?g0l8xQ|x!ZZJ)>uXa zKLynWmH1}fL7m$>rmwfiEmXT2%e?p7yel6LES+~raCze_ONHxkS*_9=EqiVhsGHVh zh`uu@UTJ&SDR0N(-OacD$z^+Am)KgjVmP84HOE{+4F?*`yT7xw|ni9UH8!>=JmvbV)3AfkZLpJwhPJ-UI{njB+%g0X2(}2-e<)0 zw;d?pYrOc!Xx6@!f=pZH1fwLg TelB8QU|{fc^>bP0l+XkK5f!mS literal 0 HcmV?d00001 diff --git a/examples/core/resources/text_file.txt b/examples/core/resources/text_file.txt new file mode 100644 index 000000000..72b1a8bce --- /dev/null +++ b/examples/core/resources/text_file.txt @@ -0,0 +1,18 @@ +Starting of the Lorem ipsum dolor sit amet file +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at interdum ex, et iaculis quam. Mauris consectetur, magna vel malesuada aliquam, mauris enim venenatis arcu, nec cursus orci ante a massa. Curabitur libero elit, cursus eu odio eget, suscipit rhoncus nibh. Nam justo elit, ullamcorper eget dolor et, ullamcorper tristique nulla. Nullam sagittis dolor in tristique tincidunt. Duis ac porttitor erat, a molestie sapien. Aliquam finibus in ipsum quis venenatis. +Mauris odio lorem, pharetra ut egestas quis, tristique eu mauris. Cras sed gravida velit. Suspendisse potenti. Suspendisse lobortis eleifend fermentum. Donec eu dolor est. Etiam ac felis eu ligula auctor feugiat eu quis diam. Sed eleifend id nibh porta viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi at tristique dui, nec pretium est. Mauris mollis massa quis massa aliquet efficitur. Phasellus posuere, elit id tempus consequat, massa ante scelerisque odio, finibus gravida elit tellus eget lectus. +Donec rutrum sagittis ligula a auctor. Aliquam aliquet tincidunt pulvinar. Aenean a porta ex. Aenean at sagittis nulla. Morbi congue luctus est nec gravida. In hac habitasse platea dictumst. Praesent commodo efficitur congue. Duis interdum enim in pharetra dapibus. Proin vestibulum finibus mauris vitae mollis. +Sed ultricies sed enim vel interdum. Nullam nec sagittis est, quis lobortis nunc. Donec auctor elementum velit vel pulvinar. Sed quis efficitur felis, at mollis elit. Integer id elit ante. Ut gravida ante vitae erat scelerisque scelerisque vel in massa. Praesent varius massa eu purus feugiat, non venenatis urna rhoncus. Pellentesque vehicula, tellus eu venenatis efficitur, libero eros lobortis justo, at ultricies lacus diam non libero. Sed metus nulla, consectetur in justo vitae, mollis maximus orci. Vestibulum dapibus ultrices leo, et facilisis odio molestie a. Phasellus facilisis vitae lorem quis viverra. Etiam imperdiet urna dolor, quis interdum ligula tristique id. Aliquam id dapibus enim. +Curabitur congue elit in magna tristique, sit amet porta quam viverra. Integer nec placerat libero. Praesent sem dolor, tristique eu augue non, ultricies mollis nibh. Fusce finibus, lorem sollicitudin eleifend gravida, eros quam tempus leo, ut iaculis libero ex vitae libero. Sed placerat fringilla accumsan. Nulla laoreet cursus justo nec elementum. Proin facilisis lobortis velit, a sollicitudin leo mollis eu. Aenean et leo est. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at interdum ex, et iaculis quam. Mauris consectetur, magna vel malesuada aliquam, mauris enim venenatis arcu, nec cursus orci ante a massa. Curabitur libero elit, cursus eu odio eget, suscipit rhoncus nibh. Nam justo elit, ullamcorper eget dolor et, ullamcorper tristique nulla. Nullam sagittis dolor in tristique tincidunt. Duis ac porttitor erat, a molestie sapien. Aliquam finibus in ipsum quis venenatis. +Mauris odio lorem, pharetra ut egestas quis, tristique eu mauris. Cras sed gravida velit. Suspendisse potenti. Suspendisse lobortis eleifend fermentum. Donec eu dolor est. Etiam ac felis eu ligula auctor feugiat eu quis diam. Sed eleifend id nibh porta viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi at tristique dui, nec pretium est. Mauris mollis massa quis massa aliquet efficitur. Phasellus posuere, elit id tempus consequat, massa ante scelerisque odio, finibus gravida elit tellus eget lectus. +Donec rutrum sagittis ligula a auctor. Aliquam aliquet tincidunt pulvinar. Aenean a porta ex. Aenean at sagittis nulla. Morbi congue luctus est nec gravida. In hac habitasse platea dictumst. Praesent commodo efficitur congue. Duis interdum enim in pharetra dapibus. Proin vestibulum finibus mauris vitae mollis. +Sed ultricies sed enim vel interdum. Nullam nec sagittis est, quis lobortis nunc. Donec auctor elementum velit vel pulvinar. Sed quis efficitur felis, at mollis elit. Integer id elit ante. Ut gravida ante vitae erat scelerisque scelerisque vel in massa. Praesent varius massa eu purus feugiat, non venenatis urna rhoncus. Pellentesque vehicula, tellus eu venenatis efficitur, libero eros lobortis justo, at ultricies lacus diam non libero. Sed metus nulla, consectetur in justo vitae, mollis maximus orci. Vestibulum dapibus ultrices leo, et facilisis odio molestie a. Phasellus facilisis vitae lorem quis viverra. Etiam imperdiet urna dolor, quis interdum ligula tristique id. Aliquam id dapibus enim. +wrapping text from the last available space wrapping text from the last available space wrapping text from the last available space +Curabitur congue elit in magna tristique, sit amet porta quam viverra. Integer nec placerat libero. Praesent sem dolor, tristique eu augue non, ultricies mollis nibh. Fusce finibus, lorem sollicitudin eleifend gravida, eros quam tempus leo, ut iaculis libero ex vitae libero. Sed placerat fringilla accumsan. Nulla laoreet cursus justo nec elementum. Proin facilisis lobortis velit, a sollicitudin leo mollis eu. Aenean et leo est. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at interdum ex, et iaculis quam. Mauris consectetur, magna vel malesuada aliquam, mauris enim venenatis arcu, nec cursus orci ante a massa. Curabitur libero elit, cursus eu odio eget, suscipit rhoncus nibh. Nam justo elit, ullamcorper eget dolor et, ullamcorper tristique nulla. Nullam sagittis dolor in tristique tincidunt. Duis ac porttitor erat, a molestie sapien. Aliquam finibus in ipsum quis venenatis. +Mauris odio lorem, pharetra ut egestas quis, tristique eu mauris. Cras sed gravida velit. Suspendisse potenti. Suspendisse lobortis eleifend fermentum. Donec eu dolor est. Etiam ac felis eu ligula auctor feugiat eu quis diam. Sed eleifend id nibh porta viverra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi at tristique dui, nec pretium est. Mauris mollis massa quis massa aliquet efficitur. Phasellus posuere, elit id tempus consequat, massa ante scelerisque odio, finibus gravida elit tellus eget lectus. +Donec rutrum sagittis ligula a auctor. Aliquam aliquet tincidunt pulvinar. Aenean a porta ex. Aenean at sagittis nulla. Morbi congue luctus est nec gravida. In hac habitasse platea dictumst. Praesent commodo efficitur congue. Duis interdum enim in pharetra dapibus. Proin vestibulum finibus mauris vitae mollis. +Sed ultricies sed enim vel interdum. Nullam nec sagittis est, quis lobortis nunc. Donec auctor elementum velit vel pulvinar. Sed quis efficitur felis, at mollis elit. Integer id elit ante. Ut gravida ante vitae erat scelerisque scelerisque vel in massa. Praesent varius massa eu purus feugiat, non venenatis urna rhoncus. Pellentesque vehicula, tellus eu venenatis efficitur, libero eros lobortis justo, at ultricies lacus diam non libero. Sed metus nulla, consectetur in justo vitae, mollis maximus orci. Vestibulum dapibus ultrices leo, et facilisis odio molestie a. Phasellus facilisis vitae lorem quis viverra. Etiam imperdiet urna dolor, quis interdum ligula tristique id. Aliquam id dapibus enim. +Curabitur congue elit in magna tristique, sit amet porta quam viverra. Integer nec placerat libero. Praesent sem dolor, tristique eu augue non, ultricies mollis nibh. Fusce finibus, lorem sollicitudin eleifend gravida, eros quam tempus leo, ut iaculis libero ex vitae libero. Sed placerat fringilla accumsan. Nulla laoreet cursus justo nec elementum. Proin facilisis lobortis velit, a sollicitudin leo mollis eu. Aenean et leo est. +Ending of the Lorem ipsum dolor sit amet file diff --git a/projects/VS2022/examples/core_text_file_loading.vcxproj b/projects/VS2022/examples/core_text_file_loading.vcxproj new file mode 100644 index 000000000..c2e25e042 --- /dev/null +++ b/projects/VS2022/examples/core_text_file_loading.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + core_text_file_loading + 10.0 + core_text_file_loading + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\core + 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) + /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 + 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)\ + + + + + 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 + + + + + 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 c4de89730..7a7eca297 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -391,6 +391,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "examples\core_screen_recording.vcxproj", "{9DE2FC01-A839-4F89-8319-9071D4C54821}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "examples\core_text_file_loading.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 From 085f933b172f70c54afc401a6fb1401662a8a2ff Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 17 Oct 2025 17:17:54 +0200 Subject: [PATCH 043/102] Review example formating --- examples/core/core_text_file_loading.c | 56 +++++++++++++------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/core/core_text_file_loading.c b/examples/core/core_text_file_loading.c index 0077551fd..4b334e811 100644 --- a/examples/core/core_text_file_loading.c +++ b/examples/core/core_text_file_loading.c @@ -16,7 +16,8 @@ ********************************************************************************************/ #include "raylib.h" -#include "raymath.h" // For Lerp + +#include "raymath.h" // Required for: Lerp() //------------------------------------------------------------------------------------ // Program main entry point @@ -38,35 +39,35 @@ int main(void) .zoom = 1 }; - // Loading file from resources/text_file.txt + // Loading text file from resources/text_file.txt const char *fileName = "resources/text_file.txt"; - char *fileData = LoadFileText(fileName); + char *text = LoadFileText(fileName); - // Loading all the lines + // Loading all the text lines int lineCount = 0; - char **lines = LoadTextLines(fileData, &lineCount); + char **lines = LoadTextLines(text, &lineCount); - // Just sylistic choise + // Stylistic choises int fontSize = 20; - int textTop = 25 + fontSize; // Top of the screen from where the text is rendered + int textTop = 25 + fontSize; // Top of the screen from where the text is rendered int wrapWidth = screenWidth - 20; // Wrap the lines as needed - for(int i = 0; i < lineCount; i++) + for (int i = 0; i < lineCount; i++) { int j = 0; int lastSpace = 0; // Keeping track of last valid space to insert '\n' int lastWrapStart = 0; // Keeping track of the start of this wrapped line. - while(lines[i][j] != '\0') + while (lines[i][j] != '\0') { - if(lines[i][j] == ' ') + if (lines[i][j] == ' ') { // Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function lines[i][j] = '\0'; // Checking if the text has crossed the wrapWidth, then going back and inserting a newline - if(MeasureText(lines[i] + lastWrapStart, fontSize) > wrapWidth) + if (MeasureText(lines[i] + lastWrapStart, fontSize) > wrapWidth) { lines[i][lastSpace] = '\n'; @@ -85,7 +86,7 @@ int main(void) // Calculating the total height so that we can show a scrollbar int textHeight = 0; - for(int i = 0; i < lineCount; i++) + for (int i = 0; i < lineCount; i++) { Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); textHeight += size.y + 10; @@ -96,10 +97,9 @@ int main(void) .x = screenWidth - 5, .y = 0, .width = 5, - .height = screenHeight * 100 / (textHeight - screenHeight) // Scrollbar height is just a percentage + .height = screenHeight*100/(textHeight - screenHeight) // Scrollbar height is just a percentage }; - SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -109,16 +109,17 @@ int main(void) // Update //---------------------------------------------------------------------------------- float scroll = GetMouseWheelMove(); - cam.target.y -= scroll * fontSize * 1.5; // Choosing an arbitrary speed for scroll + cam.target.y -= scroll*fontSize*1.5f; // Choosing an arbitrary speed for scroll - if(cam.target.y < 0) // Snapping to 0 if we go too far back - cam.target.y = 0; - - if(cam.target.y > textHeight - screenHeight + textTop) // Ensuring that the camera does not scroll past all text + if (cam.target.y < 0) cam.target.y = 0; // Snapping to 0 if we go too far back + + // Ensuring that the camera does not scroll past all text + if (cam.target.y > textHeight - screenHeight + textTop) cam.target.y = textHeight - screenHeight + textTop; - // Computing the position of the scrollBar depending on the percentage of text covered. - scrollBar.y = Lerp(textTop, screenHeight - scrollBar.height, (cam.target.y - textTop) / (textHeight - screenHeight)); + // Computing the position of the scrollBar depending on the percentage of text covered + scrollBar.y = Lerp(textTop, screenHeight - scrollBar.height, (cam.target.y - textTop)/(textHeight - screenHeight)); + //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- @@ -127,17 +128,16 @@ int main(void) ClearBackground(RAYWHITE); BeginMode2D(cam); - - Font defaultFont = GetFontDefault(); - // Going through all the read lines - for(int i = 0, t = textTop; i < lineCount; i++) + for (int i = 0, t = textTop; i < lineCount; i++) { // Each time we go through and calculate the height of the text to move the cursor appropriately - Vector2 size = MeasureTextEx(defaultFont, lines[i], fontSize, 2); + Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); + DrawText(lines[i], 10, t, fontSize, RED); - // Inserting extra space for real newlines, wrapped lines are rendered closer together + // Inserting extra space for real newlines, + // wrapped lines are rendered closer together t += size.y + 10; } EndMode2D(); @@ -155,7 +155,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- UnloadTextLines(lines, lineCount); - UnloadFileText(fileData); + UnloadFileText(text); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- From 9ef3448193c4d823975816472e4e9f198cea21c9 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 Oct 2025 19:47:05 +0200 Subject: [PATCH 044/102] Reviewed UUIDs --- .../examples/core_text_file_loading.vcxproj | 2 +- projects/VS2022/raylib.sln | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/projects/VS2022/examples/core_text_file_loading.vcxproj b/projects/VS2022/examples/core_text_file_loading.vcxproj index c2e25e042..15324701d 100644 --- a/projects/VS2022/examples/core_text_file_loading.vcxproj +++ b/projects/VS2022/examples/core_text_file_loading.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {2F578155-D51F-4C03-AB7F-5C5122CA46CC} Win32Proj core_text_file_loading 10.0 diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 7a7eca297..d0a886a4f 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -391,7 +391,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_highdpi_testbed", "exa EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "examples\core_screen_recording.vcxproj", "{9DE2FC01-A839-4F89-8319-9071D4C54821}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "examples\core_text_file_loading.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "examples\core_text_file_loading.vcxproj", "{2F578155-D51F-4C03-AB7F-5C5122CA46CC}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -4847,6 +4847,30 @@ Global {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x64.Build.0 = Release|x64 {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x86.ActiveCfg = Release|Win32 {9DE2FC01-A839-4F89-8319-9071D4C54821}.Release|x86.Build.0 = Release|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|ARM64.Build.0 = Debug|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|x64.ActiveCfg = Debug|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|x64.Build.0 = Debug|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|x86.ActiveCfg = Debug|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Debug|x86.Build.0 = Debug|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|ARM64.ActiveCfg = Release|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|ARM64.Build.0 = Release|ARM64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x64.ActiveCfg = Release|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x64.Build.0 = Release|x64 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x86.ActiveCfg = Release|Win32 + {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From aeafce5db4a8b52371882f33dcd5f4ffacbaecac Mon Sep 17 00:00:00 2001 From: JordSant <77529699+JordSant@users.noreply.github.com> Date: Sat, 18 Oct 2025 19:50:52 +0200 Subject: [PATCH 045/102] [examples] Added: `shaders_mandelbrot_set` (#5282) * [examples] Added: `shaders_mandelbrot_set` * Simplified shader code and added comments * Comments starting with a capital letter, and some minor fixes to adhere to the convention --- .../shaders/glsl100/mandelbrot_set.fs | 61 ++ .../shaders/glsl120/mandelbrot_set.fs | 59 ++ .../shaders/glsl330/mandelbrot_set.fs | 58 ++ examples/shaders/shaders_mandelbrot_set.c | 224 +++++++ examples/shaders/shaders_mandelbrot_set.png | Bin 0 -> 71902 bytes .../examples/shaders_mandelbrot_set.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 2 + 7 files changed, 973 insertions(+) create mode 100644 examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs create mode 100644 examples/shaders/resources/shaders/glsl120/mandelbrot_set.fs create mode 100644 examples/shaders/resources/shaders/glsl330/mandelbrot_set.fs create mode 100644 examples/shaders/shaders_mandelbrot_set.c create mode 100644 examples/shaders/shaders_mandelbrot_set.png create mode 100644 projects/VS2022/examples/shaders_mandelbrot_set.vcxproj diff --git a/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs new file mode 100644 index 000000000..aab8514e8 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs @@ -0,0 +1,61 @@ +#version 100 + +#define PI 3.1415926535897932384626433832795 + +precision highp float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec2 offset; // Offset of the scale +uniform float zoom; // Zoom of the scale +// NOTE: Maximum number of shader for-loop iterations depend on GPU, +// For example, on RasperryPi for this examply only supports up to 60 +uniform int maxIterations; // Max iterations per pixel + +const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity +const float max2 = max*max; // Square of max to avoid computing square root + +void main() +{ + // The pixel coordinates are scaled so they are on the mandelbrot scale + // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom + vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; + c.x += offset.x; + c.y += offset.y; + float a = 0.0; + float b = 0.0; + + // The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function + // Fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0 + // Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i + + int iter = 0; + while (iter < maxIterations) + { + float aa = a*a; + float bb = b*b; + if (aa + bb > max2) + break; + + float twoab = 2.0*a*b; + a = aa - bb + c.x; + b = twoab + c.y; + + ++iter; + } + + if (iter >= maxIterations) + { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + else + { + float normR = float(iter - (iter/55)*55)/55.0; + float normG = float(iter - (iter/69)*69)/69.0; + float normB = float(iter - (iter/40)*40)/40.0; + + gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); + } +} diff --git a/examples/shaders/resources/shaders/glsl120/mandelbrot_set.fs b/examples/shaders/resources/shaders/glsl120/mandelbrot_set.fs new file mode 100644 index 000000000..5da3ef437 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/mandelbrot_set.fs @@ -0,0 +1,59 @@ +#version 120 + +#define PI 3.1415926535897932384626433832795 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +uniform vec2 offset; // Offset of the scale +uniform float zoom; // Zoom of the scale +// NOTE: Maximum number of shader for-loop iterations depend on GPU, +// For example, on RasperryPi for this examply only supports up to 60 +uniform int maxIterations; // Max iterations per pixel + +const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity +const float max2 = max*max; // Square of max to avoid computing square root + +void main() +{ + // The pixel coordinates are scaled so they are on the mandelbrot scale + // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom + vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; + c.x += offset.x; + c.y += offset.y; + float a = 0.0; + float b = 0.0; + + // The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function + // Fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0 + // Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i + + int iter = 0; + while (iter < maxIterations) + { + float aa = a*a; + float bb = b*b; + if (aa + bb > max2) + break; + + float twoab = 2.0*a*b; + a = aa - bb + c.x; + b = twoab + c.y; + + ++iter; + } + + if (iter >= maxIterations) + { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + else + { + float normR = float(iter - (iter/55)*55)/55.0; + float normG = float(iter - (iter/69)*69)/69.0; + float normB = float(iter - (iter/40)*40)/40.0; + + gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); + } +} diff --git a/examples/shaders/resources/shaders/glsl330/mandelbrot_set.fs b/examples/shaders/resources/shaders/glsl330/mandelbrot_set.fs new file mode 100644 index 000000000..bde74565f --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/mandelbrot_set.fs @@ -0,0 +1,58 @@ +#version 330 + +#define PI 3.1415926535897932384626433832795 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Output fragment color +out vec4 finalColor; + +uniform vec2 offset; // Offset of the scale +uniform float zoom; // Zoom of the scale +uniform int maxIterations; // Max iterations per pixel + +const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity +const float max2 = max*max; // Square of max to avoid computing square root + +void main() +{ + // The pixel coordinates are scaled so they are on the mandelbrot scale + // NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom + vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom; + c.x += offset.x; + c.y += offset.y; + float a = 0.0; + float b = 0.0; + + // The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function + // Fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0 + // Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i + + int iter = 0; + for (iter = 0; iter < maxIterations; ++iter) + { + float aa = a*a; + float bb = b*b; + if (aa + bb > max2) + break; + + float twoab = 2.0*a*b; + a = aa - bb + c.x; + b = twoab + c.y; + } + + if (iter >= maxIterations) + { + finalColor = vec4(0.0, 0.0, 0.0, 1.0); + } + else + { + float normR = float(iter%55)/55.0; + float normG = float(iter%69)/69.0; + float normB = float(iter%40)/40.0; + + finalColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); + } +} diff --git a/examples/shaders/shaders_mandelbrot_set.c b/examples/shaders/shaders_mandelbrot_set.c new file mode 100644 index 000000000..c8d0ce8d3 --- /dev/null +++ b/examples/shaders/shaders_mandelbrot_set.c @@ -0,0 +1,224 @@ +/******************************************************************************************* +* +* raylib [shaders] example - mandelbrot set +* +* Example complexity rating: [★★★☆] 3/4 +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version +* +* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3) +* +* Example originally created with raylib 5.6, last time updated with raylib 5.6 +* +* Example contributed by Jordi Santonja (@JordSant) +* Based on previous work by Josh Colclough (@joshcol9232) +* +* 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) 2025 Jordi Santonja (@JordSant) +* +********************************************************************************************/ + +#include "raylib.h" +#include + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +// A few good interesting places +const float pointsOfInterest[6][3] = +{ + { -1.76826775f, -0.00422996283f, 28435.9238f }, + { 0.322004497f, -0.0357099883f, 56499.7266f }, + { -0.748880744f, -0.0562955774f, 9237.59082f }, + { -1.78385007f, -0.0156200649f, 14599.5283f }, + { -0.0985441282f, -0.924688697f, 26259.8535f }, + { 0.317785531f, -0.0322612226f, 29297.9258f }, +}; + +const int screenWidth = 800; +const int screenHeight = 450; +const float zoomSpeed = 1.01f; +const float offsetSpeedMul = 2.0f; + +const float startingZoom = 0.6f; +const float startingOffset[2] = { -0.5f, 0.0f }; + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - mandelbrot set"); + + // Load mandelbrot set shader + // NOTE: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader + Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/mandelbrot_set.fs", GLSL_VERSION)); + + // Create a RenderTexture2D to be used for render to texture + RenderTexture2D target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight()); + + // Offset and zoom to draw the mandelbrot set at. (centered on screen and default size) + float offset[2] = { startingOffset[0], startingOffset[1] }; + float zoom = startingZoom; + // Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in + // The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys + int maxIterations = 333; + float maxIterationsMultiplier = 166.5f; + + // Get variable (uniform) locations on the shader to connect with the program + // NOTE: If uniform variable could not be found in the shader, function returns -1 + int zoomLoc = GetShaderLocation(shader, "zoom"); + int offsetLoc = GetShaderLocation(shader, "offset"); + int maxIterationsLoc = GetShaderLocation(shader, "maxIterations"); + + // Upload the shader uniform values! + SetShaderValue(shader, zoomLoc, &zoom, SHADER_UNIFORM_FLOAT); + SetShaderValue(shader, offsetLoc, offset, SHADER_UNIFORM_VEC2); + SetShaderValue(shader, maxIterationsLoc, &maxIterations, SHADER_UNIFORM_INT); + + bool showControls = true; // Show controls + + 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 + //---------------------------------------------------------------------------------- + bool updateShader = false; + + // Press [1 - 6] to reset c to a point of interest + if (IsKeyPressed(KEY_ONE) || + IsKeyPressed(KEY_TWO) || + IsKeyPressed(KEY_THREE) || + IsKeyPressed(KEY_FOUR) || + IsKeyPressed(KEY_FIVE) || + IsKeyPressed(KEY_SIX)) + { + int interestIndex = 0; + if (IsKeyPressed(KEY_ONE)) interestIndex = 0; + else if (IsKeyPressed(KEY_TWO)) interestIndex = 1; + else if (IsKeyPressed(KEY_THREE)) interestIndex = 2; + else if (IsKeyPressed(KEY_FOUR)) interestIndex = 3; + else if (IsKeyPressed(KEY_FIVE)) interestIndex = 4; + else if (IsKeyPressed(KEY_SIX)) interestIndex = 5; + + offset[0] = pointsOfInterest[interestIndex][0]; + offset[1] = pointsOfInterest[interestIndex][1]; + zoom = pointsOfInterest[interestIndex][2]; + updateShader = true; + } + + // If "R" is pressed, reset zoom and offset + if (IsKeyPressed(KEY_R)) + { + offset[0] = startingOffset[0]; + offset[1] = startingOffset[1]; + zoom = startingZoom; + updateShader = true; + } + + if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls + + // Change number of max iterations with UP and DOWN keys + // WARNING: Increasing the number of max iterations greatly impacts performance + if (IsKeyPressed(KEY_UP)) + { + maxIterationsMultiplier *= 1.4f; + updateShader = true; + } + else if (IsKeyPressed(KEY_DOWN)) + { + maxIterationsMultiplier /= 1.4f; + updateShader = true; + } + + // If either left or right button is pressed, zoom in/out + if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) + { + // Change zoom. If Mouse left -> zoom in. Mouse right -> zoom out + zoom *= IsMouseButtonDown(MOUSE_BUTTON_LEFT)? zoomSpeed : (1.0f/zoomSpeed); + + const Vector2 mousePos = GetMousePosition(); + Vector2 offsetVelocity; + // Find the velocity at which to change the camera. Take the distance of the mouse + // From the center of the screen as the direction, and adjust magnitude based on the current zoom + offsetVelocity.x = (mousePos.x/(float)screenWidth - 0.5f)*offsetSpeedMul/zoom; + offsetVelocity.y = (mousePos.y/(float)screenHeight - 0.5f)*offsetSpeedMul/zoom; + + // Apply move velocity to camera + offset[0] += GetFrameTime()*offsetVelocity.x; + offset[1] += GetFrameTime()*offsetVelocity.y; + + updateShader = true; + } + + // In case a parameter has been changed, update the shader values + if (updateShader) + { + // As we zoom in, increase the number of max iterations to get more detail + // Aproximate formula, but it works-ish + maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier); + + // Update the shader uniform values! + SetShaderValue(shader, zoomLoc, &zoom, SHADER_UNIFORM_FLOAT); + SetShaderValue(shader, offsetLoc, offset, SHADER_UNIFORM_VEC2); + SetShaderValue(shader, maxIterationsLoc, &maxIterations, SHADER_UNIFORM_INT); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + // Using a render texture to draw Mandelbrot set + BeginTextureMode(target); // Enable drawing to texture + ClearBackground(BLACK); // Clear the render texture + + // Draw a rectangle in shader mode to be used as shader canvas + // NOTE: Rectangle uses font white character texture coordinates, + // So shader can not be applied here directly because input vertexTexCoord + // Do not represent full screen coordinates (space where want to apply shader) + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLACK); + EndTextureMode(); + + BeginDrawing(); + ClearBackground(BLACK); // Clear screen background + + // Draw the saved texture and rendered mandelbrot set with shader + // NOTE: We do not invert texture on Y, already considered inside shader + BeginShaderMode(shader); + // WARNING: If FLAG_WINDOW_HIGHDPI is enabled, HighDPI monitor scaling should be considered + // When rendering the RenderTexture2D to fit in the HighDPI scaled Window + DrawTextureEx(target.texture, (Vector2){ 0.0f, 0.0f }, 0.0f, 1.0f, WHITE); + EndShaderMode(); + + if (showControls) + { + DrawText("Press Mouse buttons right/left to zoom in/out and move", 10, 15, 10, RAYWHITE); + DrawText("Press F1 to toggle these controls", 10, 30, 10, RAYWHITE); + DrawText("Press [1 - 6] to change point of interest", 10, 45, 10, RAYWHITE); + DrawText("Press UP | DOWN to change number of iterations", 10, 60, 10, RAYWHITE); + DrawText("Press R to recenter the camera", 10, 75, 10, RAYWHITE); + } + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); // Unload shader + UnloadRenderTexture(target); // Unload render texture + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_mandelbrot_set.png b/examples/shaders/shaders_mandelbrot_set.png new file mode 100644 index 0000000000000000000000000000000000000000..6d112931d3a3b23a6cae48f6319b495164280359 GIT binary patch literal 71902 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 z%0A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 Q1_lNOPgg&ebxsLQ0Iw_X6#xJL literal 0 HcmV?d00001 diff --git a/projects/VS2022/examples/shaders_mandelbrot_set.vcxproj b/projects/VS2022/examples/shaders_mandelbrot_set.vcxproj new file mode 100644 index 000000000..4ed5581e1 --- /dev/null +++ b/projects/VS2022/examples/shaders_mandelbrot_set.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6} + Win32Proj + shaders_mandelbrot_set + 10.0 + shaders_mandelbrot_set + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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 + + + $(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) + /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 + 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)\ + + + + + 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 + + + + + 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 d0a886a4f..ef46f8fe1 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -393,6 +393,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_screen_recording", "ex EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "examples\core_text_file_loading.vcxproj", "{2F578155-D51F-4C03-AB7F-5C5122CA46CC}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_mandelbrot_set", "examples\shaders_mandelbrot_set.vcxproj", "{1C829D1A-892C-451C-AF0B-AC65C85F5CC6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 From de8575b16e9042d2a0d7f291bb6e696098f7c54b Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 18 Oct 2025 19:54:35 +0200 Subject: [PATCH 046/102] Update raylib.sln --- projects/VS2022/raylib.sln | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index ef46f8fe1..ec35ed5e5 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -4873,6 +4873,30 @@ Global {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x64.Build.0 = Release|x64 {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x86.ActiveCfg = Release|Win32 {2F578155-D51F-4C03-AB7F-5C5122CA46CC}.Release|x86.Build.0 = Release|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|ARM64.Build.0 = Debug|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|x64.ActiveCfg = Debug|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|x64.Build.0 = Debug|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|x86.ActiveCfg = Debug|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Debug|x86.Build.0 = Debug|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|ARM64.ActiveCfg = Release|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|ARM64.Build.0 = Release|ARM64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x64.ActiveCfg = Release|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x64.Build.0 = Release|x64 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x86.ActiveCfg = Release|Win32 + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5070,6 +5094,8 @@ Global {EA4AD5A7-DB95-43C0-9A67-2D94146BCF91} = {278D8859-20B1-428F-8448-064F46E1F021} {1ACC8236-EF4E-44B0-BD0C-AB1D95D5890F} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {9DE2FC01-A839-4F89-8319-9071D4C54821} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {2F578155-D51F-4C03-AB7F-5C5122CA46CC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {1C829D1A-892C-451C-AF0B-AC65C85F5CC6} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From 7ae3eb5d3a25f865c2947bf4b6a0ed2dc101ab4d Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 Oct 2025 11:10:08 +0200 Subject: [PATCH 047/102] Create web_basic_window.png --- examples/others/web_basic_window.png | Bin 0 -> 10297 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/others/web_basic_window.png diff --git a/examples/others/web_basic_window.png b/examples/others/web_basic_window.png new file mode 100644 index 0000000000000000000000000000000000000000..346184417a436343a769ba38a9ad9cfda0195181 GIT binary patch literal 10297 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 rcxALa7%dM*%Y)JKz+i&p5A#a1(8!d Date: Mon, 20 Oct 2025 11:13:45 +0200 Subject: [PATCH 048/102] REXM: Update examples collection --- examples/Makefile | 1 + examples/Makefile.Web | 5 +++++ examples/README.md | 10 ++++++---- examples/examples_list.txt | 2 ++ tools/rexm/examples_report.md | 4 +++- tools/rexm/examples_report_issues.md | 2 +- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index a9732679d..ef7cb5948 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -664,6 +664,7 @@ SHADERS = \ shaders/shaders_hybrid_rendering \ shaders/shaders_julia_set \ shaders/shaders_lightmap_rendering \ + shaders/shaders_mandelbrot_set \ shaders/shaders_mesh_instancing \ shaders/shaders_model_shader \ shaders/shaders_multi_sample2d \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 88843af09..5d4f3ffab 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -664,6 +664,7 @@ SHADERS = \ shaders/shaders_hybrid_rendering \ shaders/shaders_julia_set \ shaders/shaders_lightmap_rendering \ + shaders/shaders_mandelbrot_set \ shaders/shaders_mesh_instancing \ shaders/shaders_model_shader \ shaders/shaders_multi_sample2d \ @@ -1307,6 +1308,10 @@ shaders/shaders_lightmap_rendering: shaders/shaders_lightmap_rendering.c --preload-file shaders/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png \ --preload-file shaders/resources/spark_flame.png@resources/spark_flame.png +shaders/shaders_mandelbrot_set: shaders/shaders_mandelbrot_set.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file shaders/resources/shaders/glsl100/mandelbrot_set.fs@resources/shaders/glsl100/mandelbrot_set.fs + shaders/shaders_mesh_instancing: shaders/shaders_mesh_instancing.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/shaders/glsl100/lighting_instancing.vs@resources/shaders/glsl100/lighting_instancing.vs \ diff --git a/examples/README.md b/examples/README.md index b40966a5a..19d110344 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,9 +17,9 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 185] +## EXAMPLES COLLECTION [TOTAL: 187] -### category: core [44] +### category: core [45] Examples using raylib[core](../src/rcore.c) platform functionality like window creation, inputs, drawing modes and system functionality. @@ -69,6 +69,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_highdpi_testbed](core/core_highdpi_testbed.c) | core_highdpi_testbed | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_screen_recording](core/core_screen_recording.c) | core_screen_recording | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Ramon Santamaria](https://github.com/raysan5) | | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | +| [core_text_file_loading](core/core_text_file_loading.c) | core_text_file_loading | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) | ### category: shapes [31] @@ -104,7 +105,7 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | shapes_kaleidoscope | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | shapes_clock_of_clocks | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | -| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [[Balamurugan R]](https://github.com/[Bala050814]) | +| [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [Balamurugan R](https://github.com/Bala050814) | | [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | | [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | shapes_starfield_effect | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | @@ -195,7 +196,7 @@ Examples using raylib models functionality, including models loading/generation | [models_basic_voxel](models/models_basic_voxel.c) | models_basic_voxel | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) | | [models_rotating_cube](models/models_rotating_cube.c) | models_rotating_cube | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | -### category: shaders [30] +### category: shaders [31] Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module. @@ -231,6 +232,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete | [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | shaders_lightmap_rendering | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | shaders_rounded_rectangle | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | | [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | shaders_depth_rendering | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) | +| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | shaders_mandelbrot_set | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | ### category: audio [8] diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 9989f940f..2a1b9c0b7 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -192,3 +192,5 @@ others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flas others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5 +core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04 +shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index e058e09a7..fcc1f8839 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -204,4 +204,6 @@ Example elements validated: | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| web_basic_window | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_text_file_loading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shaders_mandelbrot_set | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | diff --git a/tools/rexm/examples_report_issues.md b/tools/rexm/examples_report_issues.md index 3136c2709..5de76a17a 100644 --- a/tools/rexm/examples_report_issues.md +++ b/tools/rexm/examples_report_issues.md @@ -27,4 +27,4 @@ Example elements validated: | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| web_basic_window | ✔ | ❌ | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| web_basic_window | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From 8604085b6ea6e6fb2345742a8a45c43534333267 Mon Sep 17 00:00:00 2001 From: JordSant <77529699+JordSant@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:18:15 +0200 Subject: [PATCH 049/102] [examples] Fixed `shaders_mandelbrot_set` for WebGL (#5286) --- .../shaders/glsl100/mandelbrot_set.fs | 35 ++++++++++--------- examples/shaders/shaders_mandelbrot_set.c | 5 +++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs index aab8514e8..fb6dee8b3 100644 --- a/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs +++ b/examples/shaders/resources/shaders/glsl100/mandelbrot_set.fs @@ -17,6 +17,9 @@ uniform int maxIterations; // Max iterations per pixel const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity const float max2 = max*max; // Square of max to avoid computing square root +// WebGL shaders for loop iteration limit only const +const int maxIterationsLimit = 20000; + void main() { // The pixel coordinates are scaled so they are on the mandelbrot scale @@ -31,31 +34,29 @@ void main() // Fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0 // Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i - int iter = 0; - while (iter < maxIterations) + for (int iter = 0; iter < maxIterationsLimit; ++iter) { float aa = a*a; float bb = b*b; + if (iter >= maxIterations) + { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + return; + } if (aa + bb > max2) - break; + { + float normR = float(iter - (iter/55)*55)/55.0; + float normG = float(iter - (iter/69)*69)/69.0; + float normB = float(iter - (iter/40)*40)/40.0; + + gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); + return; + } float twoab = 2.0*a*b; a = aa - bb + c.x; b = twoab + c.y; - - ++iter; } - if (iter >= maxIterations) - { - gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); - } - else - { - float normR = float(iter - (iter/55)*55)/55.0; - float normG = float(iter - (iter/69)*69)/69.0; - float normB = float(iter - (iter/40)*40)/40.0; - - gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0); - } + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } diff --git a/examples/shaders/shaders_mandelbrot_set.c b/examples/shaders/shaders_mandelbrot_set.c index c8d0ce8d3..a373c518a 100644 --- a/examples/shaders/shaders_mandelbrot_set.c +++ b/examples/shaders/shaders_mandelbrot_set.c @@ -70,8 +70,13 @@ int main(void) float zoom = startingZoom; // Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in // The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys +#if defined(PLATFORM_DESKTOP) int maxIterations = 333; float maxIterationsMultiplier = 166.5f; +#else + int maxIterations = 43; + float maxIterationsMultiplier = 22.0f; +#endif // Get variable (uniform) locations on the shader to connect with the program // NOTE: If uniform variable could not be found in the shader, function returns -1 From 74f2a899d945ec9014851ca75dbf1394687058f8 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 Oct 2025 19:09:37 +0200 Subject: [PATCH 050/102] Update rshapes.c --- src/rshapes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rshapes.c b/src/rshapes.c index 55f7d7fb9..2b5854f86 100644 --- a/src/rshapes.c +++ b/src/rshapes.c @@ -1432,6 +1432,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) Rectangle shapeRect = GetShapesTextureRectangle(); rlBegin(RL_QUADS); + rlNormal3f(0.0f, 0.0f, 1.0f); rlColor4ub(color.r, color.g, color.b, color.a); rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height); @@ -1441,7 +1442,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) rlVertex2f(v2.x, v2.y); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height); - rlVertex2f(v2.x, v2.y); + rlVertex2f(v3.x, v3.y); rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height); rlVertex2f(v3.x, v3.y); From ec3cb7045f710b202eb9ea15f64ca8fa9c779136 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 Oct 2025 19:09:56 +0200 Subject: [PATCH 051/102] Update rcore.c --- src/rcore.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index f87b68783..5dea97c22 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -679,12 +679,15 @@ void InitWindow(int width, int height, const char *title) // Initialize window data CORE.Window.screen.width = width; CORE.Window.screen.height = height; + CORE.Window.currentFbo.width = CORE.Window.screen.width; + CORE.Window.currentFbo.height = CORE.Window.screen.height; + CORE.Window.eventWaiting = false; - CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default + CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default if ((title != NULL) && (title[0] != 0)) CORE.Window.title = title; // Initialize global input state - memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0 + memset(&CORE.Input, 0, sizeof(CORE.Input)); // Reset CORE.Input structure to 0 CORE.Input.Keyboard.exitKey = KEY_ESCAPE; CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f }; CORE.Input.Mouse.cursor = MOUSE_CURSOR_ARROW; @@ -696,7 +699,7 @@ void InitWindow(int width, int height, const char *title) if (result != 0) { - TRACELOG(LOG_WARNING, "SYSTEM: Failed to initialize Platform"); + TRACELOG(LOG_WARNING, "SYSTEM: Failed to initialize platform"); return; } //-------------------------------------------------------------- From 166420429106692f2f66d9bec39121ed9617f00f Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 Oct 2025 19:10:41 +0200 Subject: [PATCH 052/102] REVIEWED: New Win32 platform backend to accomodate `rlsw` Software Renderer --- src/platforms/rcore_desktop_win32.c | 695 +++++++++++++++++----------- src/rlgl.h | 33 +- 2 files changed, 432 insertions(+), 296 deletions(-) diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 3ccd4d3bd..7ac6138bd 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -91,22 +91,24 @@ typedef struct { HWND hwnd; // Window handler HDC hdc; // Graphic context handler HGLRC glContext; // OpenGL context handler + // Software renderer variables HDC hdcmem; // Memory graphic context handler HBITMAP hbitmap; // GDI bitmap handler unsigned int *pixels; // Pointer to pixel data buffer (BGRA format) - LARGE_INTEGER timerFrequency; unsigned int appScreenWidth; unsigned int appScreenHeight; unsigned int desiredFlags; - bool cursorEnabled; + + LARGE_INTEGER timerFrequency; } PlatformData; // Define WGL function pointer types (no wglext.h needed) typedef HGLRC (WINAPI *PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int *); typedef BOOL (WINAPI *PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC, const int *, const FLOAT *, UINT, int *, UINT *); typedef BOOL (WINAPI *PFNWGLSWAPINTERVALEXTPROC)(int); +typedef const char *(WINAPI *PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc); //---------------------------------------------------------------------------------- // Global Variables Definition @@ -119,6 +121,7 @@ static PlatformData platform = { 0 }; // Platform specific data static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL; static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; +static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL; // -------------------------------------------------------------------------------- // This part of the file contains pure functions that never access global state @@ -133,10 +136,10 @@ static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; // Defines and Macros //---------------------------------------------------------------------------------- #define A_TO_W_ALLOCA(outWstr, inAnsi) do { \ - size_t len = AToWLen(inAnsi); \ - outWstr = (WCHAR *)alloca(sizeof(WCHAR)*(len + 1)); \ - AToWCopy(outWstr, len, inAnsi); \ - outWstr[len] = 0; \ + size_t outLen = AToWLen(inAnsi); \ + outWstr = (WCHAR *)alloca(sizeof(WCHAR)*(outLen + 1)); \ + AToWCopy(inAnsi, outWstr, outLen); \ + outWstr[outLen] = 0; \ } while (0) #define STYLE_MASK_ALL 0xffffffff @@ -150,7 +153,7 @@ static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; #define WINDOW_STYLE_EX 0 -#define CLASS_NAME L"RaylibWindow" +#define CLASS_NAME L"raylibWindow" #define FLAG_MASK_OPTIONAL (FLAG_VSYNC_HINT) #define FLAG_MASK_REQUIRED ~(FLAG_MASK_OPTIONAL) @@ -196,93 +199,86 @@ static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; #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_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 +#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { MIZED_NONE, MIZED_MIN, MIZED_MAX } Mized; - -typedef enum { - UPDATE_WINDOW_FIRST, - UPDATE_WINDOW_NORMAL, -} UpdateWindowKind; - -typedef enum { - SANITIZE_FLAGS_FIRST, - SANITIZE_FLAGS_NORMAL, -} SanitizeFlagsKind; - -typedef struct { - HMONITOR needle; - int index; - int matchIndex; - RECT rect; -} FindMonitorContext; +// Maximize-minimize request types +typedef enum { + MIZED_NONE, + MIZED_MIN, + MIZED_MAX +} Mized; +// Flag operations +// NOTE: Some ops need to be deferred typedef struct { DWORD set; DWORD clear; } FlagsOp; +// Monitor info type +typedef struct { + HMONITOR needle; + int index; + int matchIndex; + RECT rect; +} MonitorInfo; + //---------------------------------------------------------------------------------- // Module Internal Functions Declaration //---------------------------------------------------------------------------------- -static size_t AToWLen(const char *a) +// Get ASCII to WCHAR length +static size_t AToWLen(const char *ascii) { - int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, a, -1, NULL, 0); + int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, ascii, -1, NULL, 0); - if (sizeNeeded < 0) TRACELOG(LOG_ERROR, "Failed to calculate wide length, result=%d, error=%u", sizeNeeded, GetLastError()); + if (sizeNeeded < 0) TRACELOG(LOG_ERROR, "WIN32: Failed to calculate wide length [ERROR: %u]", GetLastError()); return sizeNeeded; } -static void AToWCopy(wchar_t *outPtr, size_t outLen, const char *a) + +// Copy ASCII to WCHAR string +static void AToWCopy(const char *ascii, wchar_t *outPtr, size_t outLen) { - int size = MultiByteToWideChar(CP_UTF8, 0, a, -1, outPtr, (int)outLen); - if (size != outLen) TRACELOG(LOG_WARNING, "WIN32: Convert %zu UTF-8 chars to WCHAR but converted %zu", outLen, size); + int size = MultiByteToWideChar(CP_UTF8, 0, ascii, -1, outPtr, (int)outLen); + if (size != outLen) TRACELOG(LOG_WARNING, "WIN32: Failed to convert %i UTF-8 chars to WCHAR, converted %i chars", outLen, size); } static bool DecoratedFromStyle(DWORD style) { if (style & STYLE_FLAGS_UNDECORATED_ON) { - if (style & STYLE_FLAGS_UNDECORATED_OFF) TRACELOG(LOG_ERROR, "FLAGS: Style 0x%x has both undecorated on/off flags", style); + if (style & STYLE_FLAGS_UNDECORATED_OFF) TRACELOG(LOG_ERROR, "WIN32: FLAGS: Style 0x%x has both undecorated on/off flags", style); return false; // Not decorated } DWORD masked = (style & STYLE_FLAGS_UNDECORATED_OFF); - if (STYLE_FLAGS_UNDECORATED_OFF != masked) TRACELOG(LOG_ERROR, "FLAGS: Style 0x%x is missing these flags 0x%x", masked, masked ^ STYLE_FLAGS_UNDECORATED_OFF); + if (STYLE_FLAGS_UNDECORATED_OFF != masked) TRACELOG(LOG_ERROR, "WIN32: FLAGS: Style 0x%x is missing flags 0x%x", masked, masked ^ STYLE_FLAGS_UNDECORATED_OFF); return true; // Decorated } -static Mized MizedFromStyle(DWORD style) -{ - // Minimized takes precedence over maximized - if (style & WS_MINIMIZE) return MIZED_MIN; - if (style & WS_MAXIMIZE) return MIZED_MAX; - return MIZED_NONE; -} - -static Mized MizedFromFlags(unsigned flags) -{ - // minimized takes precedence over maximized - if (FLAG_CHECK(flags, FLAG_WINDOW_MINIMIZED)) return MIZED_MIN; - if (flags & FLAG_WINDOW_MAXIMIZED) return MIZED_MAX; - return MIZED_NONE; -} - +// Get window style from required flags static DWORD MakeWindowStyle(unsigned flags) { - // we don't need this since we don't have any child windows, but I guess + // We don't need this since we don't have any child windows, but I guess // it improves efficiency, plus, windows adds this flag automatically anyway // so it keeps our flags in sync with the OS - DWORD style = WS_CLIPSIBLINGS ; + DWORD style = WS_CLIPSIBLINGS; style |= (flags & FLAG_WINDOW_HIDDEN)? 0 : WS_VISIBLE; style |= (flags & FLAG_WINDOW_RESIZABLE)? STYLE_FLAGS_RESIZABLE : 0; style |= (flags & FLAG_WINDOW_UNDECORATED)? STYLE_FLAGS_UNDECORATED_ON : STYLE_FLAGS_UNDECORATED_OFF; - switch (MizedFromFlags(flags)) + // Minimized takes precedence over maximized + int mized = MIZED_NONE; + if (FLAG_CHECK(flags, FLAG_WINDOW_MINIMIZED)) mized = MIZED_MIN; + if (flags & FLAG_WINDOW_MAXIMIZED) mized = MIZED_MAX; + + switch (mized) { case MIZED_NONE: break; case MIZED_MIN: style |= WS_MINIMIZE; break; @@ -293,15 +289,13 @@ static DWORD MakeWindowStyle(unsigned flags) return style; } -// Enforces that the actual window/platform state is in sync with raylib's flags +// Check flags state, enforces that the actual window/platform state is in sync with raylib's flags static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expectedStyle, DWORD styleCheckMask) { - //TRACELOG(LOG_INFO, "Verifying Flags 0x%x Style 0x%x Mask 0x%x", flags, expectedStyle & styleCheckMask, styleCheckMask); - DWORD styleFromFlags = MakeWindowStyle(flags); if ((styleFromFlags & styleCheckMask) != (expectedStyle & styleCheckMask)) { - TRACELOG(LOG_ERROR, "%s: window flags (0x%x) produced style 0x%x which != expected 0x%x (diff=0x%x, mask=0x%x)", + TRACELOG(LOG_ERROR, "WIN32: FLAGS: %s: window flags (0x%x) produced style 0x%x which != expected 0x%x (diff=0x%x, mask=0x%x)", context, flags, styleFromFlags & styleCheckMask, expectedStyle & styleCheckMask, (styleFromFlags & styleCheckMask) ^ (expectedStyle & styleCheckMask), styleCheckMask); } @@ -310,7 +304,7 @@ static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expect LONG actualStyle = (LONG)GetWindowLongPtrW(hwnd, GWL_STYLE); if ((actualStyle & styleCheckMask) != (expectedStyle & styleCheckMask)) { - TRACELOG(LOG_ERROR, "%s: expected style 0x%x but got 0x%x (diff=0x%x, mask=0x%x, lasterror=%lu)", + TRACELOG(LOG_ERROR, "WIN32: FLAGS: %s: expected style 0x%x but got 0x%x (diff=0x%x, mask=0x%x, lasterror=%lu)", context, expectedStyle & styleCheckMask, actualStyle & styleCheckMask, (expectedStyle & styleCheckMask) ^ (actualStyle & styleCheckMask), styleCheckMask, GetLastError()); @@ -320,7 +314,7 @@ static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expect { bool isIconic = IsIconic(hwnd); bool styleMinimized = !!(WS_MINIMIZE & actualStyle); - if (isIconic != styleMinimized) TRACELOG(LOG_ERROR, "IsIconic(%d) != WS_MINIMIZED(%d)", isIconic, styleMinimized); + if (isIconic != styleMinimized) TRACELOG(LOG_ERROR, "WIN32: FLAGS: IsIconic(%d) != WS_MINIMIZED(%d)", isIconic, styleMinimized); } if (styleCheckMask & WS_MAXIMIZE) @@ -329,49 +323,32 @@ static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expect placement.length = sizeof(placement); if (!GetWindowPlacement(hwnd, &placement)) { - TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetWindowPlacement", GetLastError()); + TRACELOG(LOG_ERROR, "WIN32: FLAGS: %s failed, error=%lu", "GetWindowPlacement", GetLastError()); } bool placementMaximized = (placement.showCmd == SW_SHOWMAXIMIZED); bool styleMaximized = WS_MAXIMIZE & actualStyle; if (placementMaximized != styleMaximized) { - TRACELOG(LOG_ERROR, "maximized state desync, placement maximized=%d (showCmd=%lu) style maximized=%d", + TRACELOG(LOG_ERROR, "WIN32: FLAGS: Maximized state desync, placement maximized=%d (showCmd=%lu) style maximized=%d", placementMaximized, placement.showCmd, styleMaximized); } } } -static SIZE PxFromPt2(float dpiScale, bool highdpiEnabled, int screenWidth, int screenHeight) -{ - // Get size in pixels from points - return (SIZE){ - highdpiEnabled? (int)((float)screenWidth*dpiScale) : screenWidth, - highdpiEnabled? (int)((float)screenHeight*dpiScale) : screenHeight, - }; -} - -static SIZE GetClientSize(HWND hwnd) -{ - RECT rect = { 0 }; - - if (GetClientRect(hwnd, &rect) == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetClientRect", GetLastError()); - - return (SIZE){ rect.right, rect.bottom }; -} - +// Calculate window size (with borders, title-bar...) from desired client size (framebuffer size) static SIZE CalcWindowSize(UINT dpi, SIZE clientSize, DWORD style) { RECT rect = { 0, 0, clientSize.cx, clientSize.cy }; int result = AdjustWindowRectExForDpi(&rect, style, 0, WINDOW_STYLE_EX, dpi); - - if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "AdjustWindowRect", GetLastError()); + if (result == 0) TRACELOG(LOG_ERROR, "WIN32: Failed to adjust window rect [ERROR: %lu]", GetLastError()); return (SIZE){ rect.right - rect.left, rect.bottom - rect.top }; } -// returns true if the window size was updated, false otherwise -static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int height, unsigned flags) +// Update window size if required +// NOTE: Returns true if the window size was updated, false otherwise +static bool UpdateWindowSize(int mode, HWND hwnd, int width, int height, unsigned flags) { if (flags & FLAG_WINDOW_MINIMIZED) return false; @@ -386,10 +363,10 @@ static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int he MONITORINFO info = { 0 }; HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); info.cbSize = sizeof(info); - if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetMonitorInfo", GetLastError()); + if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "WIN32: Failed to get monitor info [ERROR: %lu]", GetLastError()); RECT windowRect = { 0 }; - if (!GetWindowRect(hwnd, &windowRect)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetWindowRect", GetLastError()); + if (!GetWindowRect(hwnd, &windowRect)) TRACELOG(LOG_ERROR, "WIN32: Failed to get window rect [ERROR: %lu]", GetLastError()); if ((windowRect.left == info.rcMonitor.left) && (windowRect.top == info.rcMonitor.top) && @@ -402,33 +379,45 @@ static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int he info.rcMonitor.bottom - info.rcMonitor.top, SWP_NOOWNERZORDER)) { - TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowPos", GetLastError()); + TRACELOG(LOG_ERROR, "WIN32: Failed to set window position [ERROR: %lu]", GetLastError()); } return true; } + // Get size in pixels from points, considering high-dpi UINT dpi = GetDpiForWindow(hwnd); float dpiScale = ((float)dpi)/96.0f; bool dpiScaling = flags & FLAG_WINDOW_HIGHDPI; - SIZE desired = PxFromPt2(dpiScale, dpiScaling, width, height); - SIZE actual = GetClientSize(hwnd); - if ((actual.cx == desired.cx) || (actual.cy == desired.cy)) return false; + SIZE desiredSize = { + .cx = dpiScaling? (int)((float)width*dpiScale) : width, + .cy = dpiScaling? (int)((float)height*dpiScale) : height + }; - TRACELOG(LOG_INFO, "Restoring client size from [%dx%d] to [%dx%d] (dpi:%lu dpiScaling:%d app:%ix%i)", - actual.cx, actual.cy, desired.cx, desired.cy, dpi, dpiScaling, width, height); + // Get client size (framebuffer inside the window) + RECT rect = { 0 }; + GetClientRect(hwnd, &rect); + SIZE clientSize = { rect.right, rect.bottom }; - SIZE windowSize = CalcWindowSize(dpi, desired, MakeWindowStyle(flags)); - POINT windowPos = (POINT){ 0, 0 }; + // If client size is alread desired size, no need to update + if ((clientSize.cx == desiredSize.cx) || (clientSize.cy == desiredSize.cy)) return false; + + TRACELOG(LOG_INFO, "WIN32: Restoring client size from [%dx%d] to [%dx%d] (dpi:%lu dpiScaling:%d app:%ix%i)", + clientSize.cx, clientSize.cy, desiredSize.cx, desiredSize.cy, dpi, dpiScaling, width, height); + + // Calculate window size from desired framebuffer size and window flags + SIZE windowSize = CalcWindowSize(dpi, desiredSize, MakeWindowStyle(flags)); + POINT windowPos = { 0 }; UINT swpFlags = SWP_NOZORDER | SWP_FRAMECHANGED; - if (kind == UPDATE_WINDOW_FIRST) + + if (mode == 0) // UPDATE_WINDOW_FIRST { HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); - if (!monitor) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "MonitorFromWindow", GetLastError()); + if (!monitor) TRACELOG(LOG_ERROR, "WIN32: Failed to get monitor from window [ERROR: %lu]", GetLastError()); - MONITORINFO info; + MONITORINFO info = { 0 }; info.cbSize = sizeof(info); - if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetMonitorInfo", GetLastError()); + if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "WIN32: Failed to get monitor info [ERROR: %lu]", GetLastError()); #define MAX(a,b) (((a)>(b))? (a):(b)) @@ -446,15 +435,10 @@ static bool UpdateWindowSize(UpdateWindowKind kind, HWND hwnd, int width, int he //AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0); //SetWindowPos(hwnd, NULL, windowPos.x, windowPos.y, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER); - // Old code - //if (!SetWindowPos(hwnd, NULL, windowPos.x, windowPos.y, windowSize.cx, windowSize.cy, swpFlags)) - //{ - // TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowPos", GetLastError()); - //} - return true; } +// Verify if we are running in Windows 10 version 1703 (Creators Update) static BOOL IsWindows10Version1703OrGreaterWin32(void) { HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); @@ -463,7 +447,7 @@ static BOOL IsWindows10Version1703OrGreaterWin32(void) (DWORD (*)(RTL_OSVERSIONINFOEXW*, ULONG, ULONGLONG))GetProcAddress(ntdll, "RtlVerifyVersionInfo"); if (!Verify) { - TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetProcAddress 'RtlVerifyVersionInfo'", GetLastError()); + TRACELOG(LOG_ERROR, "WIN32: Failed to verify Windows version [ERROR: %lu]", GetLastError()); return 0; } @@ -472,6 +456,7 @@ static BOOL IsWindows10Version1703OrGreaterWin32(void) osvi.dwMajorVersion = 10; osvi.dwMinorVersion = 0; osvi.dwBuildNumber = 15063; // Build 15063 corresponds to Windows 10 version 1703 (Creators Update) + DWORDLONG cond = 0; VER_SET_CONDITION(cond, VER_MAJORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION(cond, VER_MINORVERSION, VER_GREATER_EQUAL); @@ -504,7 +489,8 @@ static void *WglGetProcAddress(const char *procname) return proc; } -static KeyboardKey KeyFromWparam(WPARAM wparam) +// Get key from wparam (mapping) +static KeyboardKey GetKeyFromWparam(WPARAM wparam) { switch (wparam) { @@ -687,6 +673,7 @@ static KeyboardKey KeyFromWparam(WPARAM wparam) } } +// Get cursor name static LPCWSTR GetCursorName(int cursor) { LPCWSTR name = (LPCWSTR)IDC_ARROW; @@ -710,37 +697,46 @@ static LPCWSTR GetCursorName(int cursor) return name; } -static BOOL CALLBACK CountMonitorsProc(HMONITOR handle, HDC _, LPRECT rect, LPARAM lparam) +// Count monitors process +// NOTE: Required by GetMonitorCount() +static BOOL CALLBACK CountMonitorsProc(HMONITOR handle, HDC hdc, LPRECT rect, LPARAM lparam) { int *count = (int *)lparam; *count += 1; + // Always return TRUE to continue the loop, otherwise, the caller // can't distinguish between stopping the loop and an error return TRUE; } -static BOOL CALLBACK FindMonitorProc(HMONITOR handle, HDC _, LPRECT rect, LPARAM lparam) +// Find monitor process +// NOTE: Required by GetCurrentMonitor() +static BOOL CALLBACK FindMonitorProc(HMONITOR handle, HDC hdc, LPRECT rect, LPARAM lparam) { - FindMonitorContext *c = (FindMonitorContext*)lparam; - if (handle == c->needle) + MonitorInfo *monitor = (MonitorInfo *)lparam; + + if (handle == monitor->needle) { - c->matchIndex = c->index; - c->rect = *rect; + monitor->matchIndex = monitor->index; + monitor->rect = *rect; } - c->index += 1; + monitor->index += 1; + // Always return TRUE to continue the loop, otherwise, the caller // can't distinguish between stopping the loop and an error return TRUE; } -static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *ss, FlagsOp *deferredFlags) +// Get style changed required operations flags +// NOTE: Required for deferred operations +static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *style, FlagsOp *deferredFlags) { // Check window resizable flag change bool resizable = (coreWindowFlags & FLAG_WINDOW_RESIZABLE); - bool resizableOld = ((ss->styleOld & STYLE_FLAGS_RESIZABLE) != 0); - bool resizableNew = ((ss->styleNew & STYLE_FLAGS_RESIZABLE) != 0); - if (resizable != resizableOld) TRACELOG(LOG_ERROR, "expected resizable %u but got %u", resizable, resizableOld); + bool resizableOld = ((style->styleOld & STYLE_FLAGS_RESIZABLE) != 0); + bool resizableNew = ((style->styleNew & STYLE_FLAGS_RESIZABLE) != 0); + if (resizable != resizableOld) TRACELOG(LOG_ERROR, "WIN32: Expected resizable %u but got %u", resizable, resizableOld); if (resizableOld != resizableNew) { if (resizableNew) deferredFlags->set |= FLAG_WINDOW_RESIZABLE; @@ -749,9 +745,9 @@ static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *ss, FlagsO // Check window decorated flag change bool decorated = (0 == (coreWindowFlags & FLAG_WINDOW_UNDECORATED)); - bool decoratedOld = DecoratedFromStyle(ss->styleOld); - bool decoratedNew = DecoratedFromStyle(ss->styleNew); - if (decorated != decoratedOld) TRACELOG(LOG_ERROR, "expected decorated %u but got %u", decorated, decoratedOld); + bool decoratedOld = DecoratedFromStyle(style->styleOld); + bool decoratedNew = DecoratedFromStyle(style->styleNew); + if (decorated != decoratedOld) TRACELOG(LOG_ERROR, "WIN32: Expected decorated %u but got %u", decorated, decoratedOld); if (decoratedOld != decoratedNew) { if (decoratedNew) deferredFlags->clear |= FLAG_WINDOW_UNDECORATED; @@ -760,9 +756,9 @@ static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *ss, FlagsO // Check window hidden flag change bool hidden = (coreWindowFlags & FLAG_WINDOW_HIDDEN); - bool hiddenOld = ((ss->styleOld & WS_VISIBLE) == 0); - bool hiddenNew = ((ss->styleNew & WS_VISIBLE) == 0); - if (hidden != hiddenOld) TRACELOG(LOG_ERROR, "expected hidden %u but got %u", hidden, hiddenOld); + bool hiddenOld = ((style->styleOld & WS_VISIBLE) == 0); + bool hiddenNew = ((style->styleNew & WS_VISIBLE) == 0); + if (hidden != hiddenOld) TRACELOG(LOG_ERROR, "WIN32: Expected hidden %u but got %u", hidden, hiddenOld); if (hiddenOld != hiddenNew) { if (hiddenNew) deferredFlags->set |= FLAG_WINDOW_HIDDEN; @@ -770,7 +766,9 @@ static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *ss, FlagsO } } -// Call when the window is rezised, returns true if the new window size should update the desired app size +// Adopt window resize +// NOTE: Call when the window is rezised, returns true +// if the new window size should update the desired app size static bool AdoptWindowResize(unsigned flags) { if (flags & FLAG_WINDOW_MINIMIZED) return false; @@ -805,9 +803,12 @@ static void HandleRawInput(LPARAM lparam); static void HandleWindowResize(HWND hwnd, int *width, int *height); static void UpdateWindowStyle(HWND hwnd, unsigned desiredFlags); -static unsigned SanitizeFlags(SanitizeFlagsKind kind, unsigned flags); +static unsigned SanitizeFlags(int mode, unsigned flags); static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height); // Update window flags +// Check if OpenGL extension is available +static bool IsWglExtensionAvailable(HDC hdc, const char *extension); + //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- @@ -826,20 +827,14 @@ bool WindowShouldClose(void) // Toggle fullscreen mode void ToggleFullscreen(void) { - TRACELOG(LOG_WARNING, "ToggleFullscreen not implemented"); + TRACELOG(LOG_WARNING, "WIN32: Toggle full screen functionality not implemented"); } // Toggle borderless windowed mode void ToggleBorderlessWindowed(void) { - if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) - { - ClearWindowState(FLAG_BORDERLESS_WINDOWED_MODE); - } - else - { - SetWindowState(FLAG_BORDERLESS_WINDOWED_MODE); - } + if (CORE.Window.flags & FLAG_BORDERLESS_WINDOWED_MODE) ClearWindowState(FLAG_BORDERLESS_WINDOWED_MODE); + else SetWindowState(FLAG_BORDERLESS_WINDOWED_MODE); } // Set window state: maximized, if resizable @@ -858,40 +853,95 @@ void MinimizeWindow(void) void RestoreWindow(void) { if ((CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) && - (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) - ) { - ClearWindowState(FLAG_WINDOW_MINIMIZED); - } - else - { - ClearWindowState(FLAG_WINDOW_MINIMIZED|FLAG_WINDOW_MAXIMIZED); - } + (CORE.Window.flags & FLAG_WINDOW_MINIMIZED)) ClearWindowState(FLAG_WINDOW_MINIMIZED); + else ClearWindowState(FLAG_WINDOW_MINIMIZED | FLAG_WINDOW_MAXIMIZED); } // Set window configuration state using flags void SetWindowState(unsigned int flags) { - platform.desiredFlags = SanitizeFlags(SANITIZE_FLAGS_NORMAL, CORE.Window.flags | flags); + platform.desiredFlags = SanitizeFlags(1 /*SANITIZE_FLAGS_NORMAL*/, CORE.Window.flags | flags); UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight); } // Clear window configuration state flags void ClearWindowState(unsigned int flags) { - platform.desiredFlags = SanitizeFlags(SANITIZE_FLAGS_NORMAL, CORE.Window.flags & ~flags); + platform.desiredFlags = SanitizeFlags(1 /*SANITIZE_FLAGS_NORMAL*/, CORE.Window.flags & ~flags); UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight); } // Set icon for window void SetWindowIcon(Image image) { - TRACELOG(LOG_WARNING, "SetWindowIcon not implemented"); + if (!platform.hwnd || (image.data == NULL) || (image.width <= 0) || (image.height <= 0)) return; + + HDC hdc = GetDC(platform.hwnd); + + // Create 32-bit BGRA DIB for color + BITMAPV5HEADER bi = { 0 }; + ZeroMemory(&bi, sizeof(bi)); + bi.bV5Size = sizeof(bi); + bi.bV5Width = image.width; + bi.bV5Height = -image.height; // Negative = top-down bitmap + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + unsigned char *targetBits = NULL; + HBITMAP hColorBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&targetBits, NULL, 0); + if (!hColorBitmap) + { + ReleaseDC(platform.hwnd, hdc); + return; + } + + // Copy RGBA > BGRA (Win32 expects BGRA) + for (int y = 0; y < image.height; y++) + { + for (int x = 0; x < image.width; x++) + { + int i = (y*image.width + x)*4; + targetBits[i + 0] = ((unsigned char *)image.data)[i + 2]; // B + targetBits[i + 1] = ((unsigned char *)image.data)[i + 1]; // G + targetBits[i + 2] = ((unsigned char *)image.data)[i + 0]; // R + targetBits[i + 3] = ((unsigned char *)image.data)[i + 3]; // A + } + } + + // Create mask bitmap (1-bit, all opaque) + HBITMAP hMaskBitmap = CreateBitmap(image.width, image.height, 1, 1, NULL); + + // Build icon info + ICONINFO ii = { 0 }; + ZeroMemory(&ii, sizeof(ii)); + ii.fIcon = TRUE; + ii.hbmMask = hMaskBitmap; + ii.hbmColor = hColorBitmap; + + HICON hIcon = CreateIconIndirect(&ii); + + // Clean up GDI bitmaps (icon keeps copies internally) + DeleteObject(hColorBitmap); + DeleteObject(hMaskBitmap); + ReleaseDC(platform.hwnd, hdc); + + if (hIcon) + { + // Set both large and small icons + SendMessage(platform.hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon); + SendMessage(platform.hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); + } } // Set icon for window void SetWindowIcons(Image *images, int count) { - TRACELOG(LOG_WARNING, "SetWindowIcons not implemented"); + // TODO. } void SetWindowTitle(const char *title) @@ -902,13 +952,24 @@ void SetWindowTitle(const char *title) A_TO_W_ALLOCA(titleWide, CORE.Window.title); int result = SetWindowTextW(platform.hwnd, titleWide); - if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowText", GetLastError()); + if (result == 0) TRACELOG(LOG_WARNING, "WIN32: Failed to set window title [ERROR: %lu]", GetLastError()); } // Set window position on screen (windowed mode) void SetWindowPosition(int x, int y) { - TRACELOG(LOG_WARNING, "SetWindowPosition not implemented"); + if (platform.hwnd != NULL) + { + RECT rect = { 0 }; + if (GetWindowRect(platform.hwnd, &rect)) + { + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + + // Move the window to the new position (keeping size and z-order) + SetWindowPos(platform.hwnd, NULL, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE); + } + } } // Set monitor for the current window @@ -975,15 +1036,15 @@ int GetCurrentMonitor(void) HMONITOR monitor = MonitorFromWindow(platform.hwnd, MONITOR_DEFAULTTOPRIMARY); if (!monitor) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "MonitorFromWindow", GetLastError()); - FindMonitorContext context; - context.needle = monitor; - context.index = 0; - context.matchIndex = -1; + MonitorInfo info = { 0 }; + info.needle = monitor; + info.index = 0; + info.matchIndex = -1; - int result = EnumDisplayMonitors(NULL, NULL, FindMonitorProc, (LPARAM)&context); + int result = EnumDisplayMonitors(NULL, NULL, FindMonitorProc, (LPARAM)&info); if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "EnumDisplayMonitors", GetLastError()); - return context.matchIndex; + return info.matchIndex; } // Get selected monitor position @@ -1091,10 +1152,9 @@ void HideCursor(void) // Enables cursor (unlock cursor) void EnableCursor(void) { - if (platform.cursorEnabled) TRACELOG(LOG_INFO, "EnableCursor: already enabled"); - else + if (CORE.Input.Mouse.cursorLocked) { - if (!ClipCursor(NULL)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ClipCursor", GetLastError()); + if (!ClipCursor(NULL)) TRACELOG(LOG_WARNING, "WIN32: Failed to clip cursor [ERROR: %lu]", GetLastError()); RAWINPUTDEVICE rid = { 0 }; rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC @@ -1102,18 +1162,17 @@ void EnableCursor(void) rid.dwFlags = RIDEV_REMOVE; // Add to this window even in background rid.hwndTarget = NULL; int result = RegisterRawInputDevices(&rid, 1, sizeof(rid)); - if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "RegisterRawInputDevices", GetLastError()); + if (result == 0) TRACELOG(LOG_WARNING, "WIN32: Failed to register raw input devices [ERROR: %lu]", GetLastError()); ShowCursor(); - platform.cursorEnabled = true; - TRACELOG(LOG_INFO, "EnableCursor: enabled"); + CORE.Input.Mouse.cursorLocked = false; } } // Disables cursor (lock cursor) void DisableCursor(void) { - if (platform.cursorEnabled) + if (!CORE.Input.Mouse.cursorLocked) { RAWINPUTDEVICE rid = { 0 }; rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC @@ -1121,33 +1180,31 @@ void DisableCursor(void) rid.dwFlags = RIDEV_INPUTSINK; // Add to this window even in background rid.hwndTarget = platform.hwnd; int result = RegisterRawInputDevices(&rid, 1, sizeof(rid)); - if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "RegisterRawInputDevices", GetLastError()); + if (result == 0) TRACELOG(LOG_WARNING, "WIN32: Failed to register raw input devices [ERROR: %lu]", GetLastError()); RECT clientRect = { 0 }; - if (!GetClientRect(platform.hwnd, &clientRect)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetClientRect", GetLastError()); + if (!GetClientRect(platform.hwnd, &clientRect)) TRACELOG(LOG_WARNING, "WIN32: Failed to get client rectangle [ERROR: %lu]", GetLastError()); POINT topleft = { clientRect.left, clientRect.top }; - if (!ClientToScreen(platform.hwnd, &topleft)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ClientToScreen", GetLastError()); + if (!ClientToScreen(platform.hwnd, &topleft)) TRACELOG(LOG_WARNING, "WIN32: Failed to get client to screen size [ERROR: %lu]", GetLastError()); LONG width = clientRect.right - clientRect.left; LONG height = clientRect.bottom - clientRect.top; - TRACELOG(LOG_INFO, "ClipCursor client %d,%d %d,%d (topleft %d,%d)", + TRACELOG(LOG_INFO, "WIN32: Clip cursor client rect: [%d,%d %d,%d], top-left: (%d,%d)", clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, topleft.x, topleft.y); LONG centerX = topleft.x + width/2; LONG centerY = topleft.y + height/2; RECT clipRect = { centerX, centerY, centerX + 1, centerY + 1 }; - if (!ClipCursor(&clipRect)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ClipCursor", GetLastError()); + if (!ClipCursor(&clipRect)) TRACELOG(LOG_WARNING, "WIN32: Failed to clip cursor [ERROR: %lu]", GetLastError()); CORE.Input.Mouse.previousPosition = (Vector2){ 0, 0 }; CORE.Input.Mouse.currentPosition = (Vector2){ 0, 0 }; HideCursor(); - platform.cursorEnabled = false; - TRACELOG(LOG_INFO, "DisableCursor: disabled"); + CORE.Input.Mouse.cursorLocked = true; } - else TRACELOG(LOG_INFO, "DisableCursor: already disabled"); } // Swap back buffer with front buffer (screen drawing) @@ -1163,8 +1220,8 @@ void SwapScreenBuffer(void) InvalidateRect(platform.hwnd, NULL, FALSE); UpdateWindow(platform.hwnd); #else - if (!SwapBuffers(platform.hdc)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SwapBuffers", GetLastError()); - if (!ValidateRect(platform.hwnd, NULL)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "ValidateRect", GetLastError()); + if (!SwapBuffers(platform.hdc)) TRACELOG(LOG_ERROR, "WIN32: Failed to swap buffers [ERROR: %lu]", GetLastError()); + if (!ValidateRect(platform.hwnd, NULL)) TRACELOG(LOG_ERROR, "WIN32: Failed to validate screen rect [ERROR: %lu]", GetLastError()); #endif } @@ -1216,7 +1273,7 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d // Set mouse position XY void SetMousePosition(int x, int y) { - if (platform.cursorEnabled) + if (!CORE.Input.Mouse.cursorLocked) { CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; @@ -1230,7 +1287,7 @@ void SetMouseCursor(int cursor) { LPCWSTR cursorName = GetCursorName(cursor); HCURSOR hcursor = LoadCursorW(NULL, cursorName); - if (!hcursor) TRACELOG(LOG_ERROR, "LoadCursor %d (win32 %d) failed, error=%lu", cursor, (size_t)cursorName, GetLastError()); + if (!hcursor) TRACELOG(LOG_ERROR, "WIN32: Failed to load requested cursor [ERROR: %lu]", GetLastError()); SetCursor(hcursor); CORE.Input.Mouse.cursorHidden = false; @@ -1319,6 +1376,7 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc) wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); + wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); // Setup modern pixel format if extension is available if (wglChoosePixelFormatARB) @@ -1353,10 +1411,52 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc) HGLRC realContext = NULL; if (wglCreateContextAttribsARB) { + int glContextVersionMajor = 1; + int glContextVersionMinor = 1; + int glContextProfile = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + + if (rlGetVersion() == RL_OPENGL_21) // Request OpenGL 2.1 context + { + glContextVersionMajor = 2; + glContextVersionMinor = 1; + } + else if (rlGetVersion() == RL_OPENGL_33) // Request OpenGL 3.3 context + { + glContextVersionMajor = 3; + glContextVersionMinor = 3; + } + else if (rlGetVersion() == RL_OPENGL_43) // Request OpenGL 4.3 context + { + glContextVersionMajor = 4; + glContextVersionMinor = 3; + } + else if (rlGetVersion() == RL_OPENGL_ES_20) // Request OpenGL ES 2.0 context + { + if (IsWglExtensionAvailable(platform.hdc, "WGL_EXT_create_context_es_profile") || + IsWglExtensionAvailable(platform.hdc, "WGL_EXT_create_context_es2_profile")) + { + glContextVersionMajor = 2; + glContextVersionMinor = 0; + glContextProfile = WGL_CONTEXT_ES_PROFILE_BIT_EXT; + } + else TRACELOG(LOG_WARNING, "GL: OpenGL ES context not supported by GPU"); + } + else if (rlGetVersion() == RL_OPENGL_ES_30) // Request OpenGL ES 3.0 context + { + if (IsWglExtensionAvailable(platform.hdc, "WGL_EXT_create_context_es_profile") || + IsWglExtensionAvailable(platform.hdc, "WGL_EXT_create_context_es2_profile")) + { + glContextVersionMajor = 3; + glContextVersionMinor = 0; + glContextProfile = WGL_CONTEXT_ES_PROFILE_BIT_EXT; + } + else TRACELOG(LOG_WARNING, "GL: OpenGL ES context not supported by GPU"); + } + int contextAttribs[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 3, - WGL_CONTEXT_MINOR_VERSION_ARB, 3, - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, // WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_ES_PROFILE_BIT_EXT (if supported) + WGL_CONTEXT_MAJOR_VERSION_ARB, glContextVersionMajor, + WGL_CONTEXT_MINOR_VERSION_ARB, glContextVersionMinor, + WGL_CONTEXT_PROFILE_MASK_ARB, glContextProfile, // WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, WGL_CONTEXT_ES_PROFILE_BIT_EXT (if supported) //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB [glDebugMessageCallback()] 0 // Terminator }; @@ -1387,9 +1487,11 @@ HGLRC InitOpenGL(HWND hwnd, HDC hdc) // Initialize platform: graphics, inputs and more int InitPlatform(void) { - platform.desiredFlags = SanitizeFlags(SANITIZE_FLAGS_FIRST, CORE.Window.flags); + int result = 0; + platform.appScreenWidth = CORE.Window.screen.width; platform.appScreenHeight = CORE.Window.screen.height; + platform.desiredFlags = SanitizeFlags(0 /*SANITIZE_FLAGS_FIRST*/, CORE.Window.flags); // NOTE: From this point CORE.Window.flags should always reflect the actual state of the window CORE.Window.flags = FLAG_WINDOW_HIDDEN | (platform.desiredFlags & FLAG_MASK_NO_UPDATE); @@ -1411,37 +1513,56 @@ int InitPlatform(void) } */ + HINSTANCE hInstance = GetModuleHandleW(0); + + // Define window class WNDCLASSEXW windowClass = { .cbSize = sizeof(WNDCLASSEXW), .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, .lpfnWndProc = WndProc, // Custom procedure assigned .cbWndExtra = sizeof(LONG_PTR), // extra space for the Tuple object ptr - .hInstance = GetModuleHandleW(0), + .hInstance = hInstance, .hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW), // TODO: Audit if we want to set this since we're implementing WM_SETCURSOR - .lpszClassName = CLASS_NAME //L"GLWindowClass"; + .lpszClassName = CLASS_NAME // Class name: L"raylibWindow" }; - // Register window class - if (RegisterClassExW(&windowClass) == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "RegisterClass", GetLastError()); + // Load user-provided icon if available + // NOTE: raylib resource file defaults to GLFW_ICON id, so looking for same identifier + windowClass.hIcon = LoadImageW(hInstance, L"GLFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (!windowClass.hIcon) windowClass.hIcon = LoadImageW(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); -/* - // TODO: Remove or move this code that sets the display size; should maybe go somewhere in WndProc? + // Register window class + result = (int)RegisterClassExW(&windowClass); + if (result == 0) TRACELOG(LOG_ERROR, "WIN32: Failed to register window class [ERROR: %lu]", GetLastError()); + + // Get primary monitor info POINT primaryTopLeft = { 0 }; HMONITOR monitor = MonitorFromPoint(primaryTopLeft, MONITOR_DEFAULTTOPRIMARY); if (monitor != NULL) { - MONITORINFO info; + MONITORINFO info = { 0 }; info.cbSize = sizeof(info); - if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_WARNING, "%s failed, error: %u", "GetMonitorInfo", GetLastError()); + result = (int)GetMonitorInfoW(monitor, &info); + + if (result == 0) TRACELOG(LOG_WARNING, "WIN32: DISPLAY: Failed to get monitor info [ERROR: %u]", GetLastError()); else { CORE.Window.display.width = info.rcMonitor.right - info.rcMonitor.left; CORE.Window.display.height = info.rcMonitor.bottom - info.rcMonitor.top; } } - else TRACELOG(LOG_WARNING, "MonitorFromPoint, error: %s", GetLastError()); -*/ - + else TRACELOG(LOG_WARNING, "WIN32: DISPLAY: Failed to get primary monitor from point [ERROR: %u]", GetLastError()); + + // Adjust the window rectangle so the *client area* matches desired size + // NOTE: Window width/height includes borders and title-bar + DWORD style = WS_OVERLAPPEDWINDOW; + RECT rect = { 0, 0, platform.appScreenWidth, platform.appScreenHeight }; + AdjustWindowRect(&rect, style, FALSE); + //AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, FALSE, WINDOW_STYLE_EX); + //AdjustWindowRectExForDpi(&rect, style, FALSE, WINDOW_STYLE_EX, dpi); + int windowWidth = rect.right - rect.left; + int windowHeight = rect.bottom - rect.top; + // Create window // NOTE: Title string needs to be converted to WCHAR WCHAR *titleWide = NULL; @@ -1454,13 +1575,13 @@ int InitPlatform(void) titleWide, MakeWindowStyle(CORE.Window.flags), // WS_OVERLAPPEDWINDOW | WS_VISIBLE CW_USEDEFAULT, CW_USEDEFAULT, - platform.appScreenWidth, platform.appScreenHeight, // TODO: Window size [width, height], needs to be updated? + windowWidth, windowHeight, // TODO: Window size [width, height], needs to be updated? NULL, NULL, GetModuleHandleW(NULL), NULL); if (!platform.hwnd) { - TRACELOG(LOG_ERROR, "%s failed, error=%lu", "CreateWindow", GetLastError()); + TRACELOG(LOG_ERROR, "WIN32: WINDOW: Failed to create window [ERROR: %lu]", GetLastError()); return -1; } @@ -1475,11 +1596,11 @@ int InitPlatform(void) // Initialize software framebuffer BITMAPINFO bmi = { 0 }; ZeroMemory(&bmi, sizeof(bmi)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = platform.appScreenWidth; - bmi.bmiHeader.biHeight = -(int)(platform.appScreenHeight); // Top-down bitmap - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; // 32-bit BGRA + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = platform.appScreenWidth; + bmi.bmiHeader.biHeight = -(int)(platform.appScreenHeight); // Top-down bitmap + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; // 32-bit BGRA bmi.bmiHeader.biCompression = BI_RGB; platform.hdcmem = CreateCompatibleDC(platform.hdc); @@ -1504,6 +1625,8 @@ int InitPlatform(void) //UpdateWindowSize(UPDATE_WINDOW_FIRST, platform.hwnd, platform.appScreenWidth, platform.appScreenHeight, platform.desiredFlags); UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight); + CORE.Window.render.width = CORE.Window.screen.width; + CORE.Window.render.height = CORE.Window.screen.height; CORE.Window.currentFbo.width = CORE.Window.render.width; CORE.Window.currentFbo.height = CORE.Window.render.height; TRACELOG(LOG_INFO, "DISPLAY: Device initialized successfully"); @@ -1512,17 +1635,29 @@ int InitPlatform(void) TRACELOG(LOG_INFO, " > Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height); TRACELOG(LOG_INFO, " > Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y); - CORE.Storage.basePath = GetWorkingDirectory(); + if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer + { + TRACELOG(LOG_INFO, "GL: OpenGL device information:"); + TRACELOG(LOG_INFO, " > Vendor: %s", "raylib"); + TRACELOG(LOG_INFO, " > Renderer: %s", "rlsw - OpenGL 1.1 Software Renderer"); + TRACELOG(LOG_INFO, " > Version: %s", "1.0"); + TRACELOG(LOG_INFO, " > GLSL: %s", "NOT SUPPORTED"); + } + // Initialize timming system + //---------------------------------------------------------------------------- LARGE_INTEGER time = { 0 }; QueryPerformanceCounter(&time); QueryPerformanceFrequency(&platform.timerFrequency); CORE.Time.base = time.QuadPart; InitTimer(); - - // TODO: Enable cursor? -> Use default value as 0 - platform.cursorEnabled = true; + //---------------------------------------------------------------------------- + + // Initialize storage system + //---------------------------------------------------------------------------- + CORE.Storage.basePath = GetWorkingDirectory(); + //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: WIN32: Initialized successfully"); @@ -1535,7 +1670,7 @@ void ClosePlatform(void) if (platform.hwnd) { int result = DestroyWindow(platform.hwnd); - if (result == 0) TRACELOG(LOG_WARNING, "WIN32: Error on window destroy: %u", GetLastError()); + if (result == 0) TRACELOG(LOG_WARNING, "WIN32: WINDOW: Failed on window destroy [ERROR: %u]", GetLastError()); platform.hwnd = NULL; } } @@ -1617,7 +1752,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara { // TODO: Enforce min/max size } - else TRACELOG(LOG_WARNING, "WINDOW: Trying to resize a non-resizable window"); + else TRACELOG(LOG_WARNING, "WIN32: WINDOW: Trying to resize a non-resizable window"); result = TRUE; } break; @@ -1629,19 +1764,22 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara GetStyleChangeFlagOps(CORE.Window.flags, ss, deferredFlags); UINT dpi = GetDpiForWindow(hwnd); - SIZE clientSize = GetClientSize(hwnd); + // Get client size (framebuffer inside the window) + RECT rect = { 0 }; + GetClientRect(hwnd, &rect); + SIZE clientSize = { rect.right, rect.bottom }; SIZE oldSize = CalcWindowSize(dpi, clientSize, ss->styleOld); SIZE newSize = CalcWindowSize(dpi, clientSize, ss->styleNew); if (oldSize.cx != newSize.cx || oldSize.cy != newSize.cy) { - TRACELOG(LOG_INFO, "resize from style change: %dx%d to %dx%d", oldSize.cx, oldSize.cy, newSize.cx, newSize.cy); + TRACELOG(LOG_INFO, "WIN32: WINDOW: Resize from style change [%dx%d] to [%dx%d]", oldSize.cx, oldSize.cy, newSize.cx, newSize.cy); if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) { // looks like windows will automatically "unminimize" a window // if a style changes modifies it's size - TRACELOG(LOG_INFO, "style change modifed window size, removing maximized flag"); + TRACELOG(LOG_INFO, "WIN32: WINDOW: Style change modifed window size, removing maximized flag"); deferredFlags->clear |= FLAG_WINDOW_MAXIMIZED; } } @@ -1650,27 +1788,20 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara case WM_WINDOWPOSCHANGING: { WINDOWPOS *pos = (WINDOWPOS *)lparam; - if (pos->flags & SWP_SHOWWINDOW) - { - //if (pos->flags & SWP_HIDEWINDOW) abort(); - deferredFlags->clear |= FLAG_WINDOW_HIDDEN; - } - else if (pos->flags & SWP_HIDEWINDOW) - { - deferredFlags->set |= FLAG_WINDOW_HIDDEN; - } + if (pos->flags & SWP_SHOWWINDOW) deferredFlags->clear |= FLAG_WINDOW_HIDDEN; + else if (pos->flags & SWP_HIDEWINDOW) deferredFlags->set |= FLAG_WINDOW_HIDDEN; Mized mized = MIZED_NONE; bool isIconic = IsIconic(hwnd); bool styleMinimized = !!(WS_MINIMIZE & GetWindowLongPtrW(hwnd, GWL_STYLE)); - if (isIconic != styleMinimized) TRACELOG(LOG_WARNING, "IsIconic(%d) != WS_MINIMIZED(%d)", isIconic, styleMinimized); + if (isIconic != styleMinimized) TRACELOG(LOG_WARNING, "WIN32: IsIconic state different from WS_MINIMIZED state"); if (isIconic) mized = MIZED_MIN; else { WINDOWPLACEMENT placement; placement.length = sizeof(placement); - if (!GetWindowPlacement(hwnd, &placement)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetWindowPlacement", GetLastError()); + if (!GetWindowPlacement(hwnd, &placement)) TRACELOG(LOG_ERROR, "WIN32: WINDOW: FAiled to get monitor placement [ERROR: %lu]", GetLastError()); if (placement.showCmd == SW_SHOWMAXIMIZED) mized = MIZED_MAX; } @@ -1683,19 +1814,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); MONITORINFO info; info.cbSize = sizeof(info); - if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetMonitorInfo", GetLastError()); + if (!GetMonitorInfoW(monitor, &info)) TRACELOG(LOG_ERROR, "WIN32: MONITOR: Failed to get monitor info [ERROR: %lu]", GetLastError()); if ((pos->x == info.rcMonitor.left) && (pos->y == info.rcMonitor.top) && (pos->cx == (info.rcMonitor.right - info.rcMonitor.left)) && - (pos->cy == (info.rcMonitor.bottom - info.rcMonitor.top))) - { - deferredFlags->set |= FLAG_BORDERLESS_WINDOWED_MODE; - } - else - { - deferredFlags->clear |= FLAG_BORDERLESS_WINDOWED_MODE; - } + (pos->cy == (info.rcMonitor.bottom - info.rcMonitor.top))) deferredFlags->set |= FLAG_BORDERLESS_WINDOWED_MODE; + else deferredFlags->clear |= FLAG_BORDERLESS_WINDOWED_MODE; } break; case MIZED_MIN: @@ -1739,7 +1864,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara float dpiScale = ((float)newDpi)/96.0f; bool dpiScaling = CORE.Window.flags & FLAG_WINDOW_HIGHDPI; - SIZE desired = PxFromPt2(dpiScale, dpiScaling, platform.appScreenWidth, platform.appScreenHeight); + // Get size in pixels from points + SIZE desired = { + .cx = dpiScaling? (int)((float)platform.appScreenWidth*dpiScale) : platform.appScreenWidth, + .cy = dpiScaling? (int)((float)platform.appScreenHeight*dpiScale) : platform.appScreenHeight + }; inoutSize->cx = desired.cx; inoutSize->cy = desired.cy; @@ -1747,18 +1876,14 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara } break; case WM_DPICHANGED: { - RECT *suggestedRect = (RECT*)lparam; + RECT *suggestedRect = (RECT *)lparam; + // Never set the window size to anything other than the suggested rect here // Doing so can cause a window to stutter between monitors when transitioning between them - if (!SetWindowPos(hwnd, NULL, - suggestedRect->left, - suggestedRect->top, - suggestedRect->right - suggestedRect->left, - suggestedRect->bottom - suggestedRect->top, - SWP_NOZORDER | SWP_NOACTIVATE)) - { - TRACELOG(LOG_ERROR, "%s failed, error=%lu", "SetWindowPos", GetLastError()); - } + int result = (int)SetWindowPos(hwnd, NULL, suggestedRect->left, suggestedRect->top, + suggestedRect->right - suggestedRect->left, suggestedRect->bottom - suggestedRect->top, SWP_NOZORDER | SWP_NOACTIVATE); + if (result == 0) TRACELOG(LOG_ERROR, "Failed to set window position [ERROR: %lu]", GetLastError()); + } break; case WM_SETCURSOR: { @@ -1789,7 +1914,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara } break; case WM_MOUSEMOVE: { - if (platform.cursorEnabled) + if (!CORE.Input.Mouse.cursorLocked) { CORE.Input.Mouse.currentPosition.x = (float)GET_X_LPARAM(lparam); CORE.Input.Mouse.currentPosition.y = (float)GET_Y_LPARAM(lparam); @@ -1833,32 +1958,23 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara } //------------------------------------------------------------------------------------ - // Sanity check - if (platform.hwnd == hwnd) - { - CheckFlags("After WndProc", hwnd, CORE.Window.flags, MakeWindowStyle(CORE.Window.flags), mask); - } + // Sanity check for flags + if (platform.hwnd == hwnd) CheckFlags("After WndProc", hwnd, CORE.Window.flags, MakeWindowStyle(CORE.Window.flags), mask); // Operations to execute after the above check - if (flagsOp.set & flagsOp.clear) - { - TRACELOG(LOG_ERROR, "the flags 0x%x were both set and cleared!", flagsOp.set & flagsOp.clear); - } + if (flagsOp.set & flagsOp.clear) TRACELOG(LOG_WARNING, "WIN32: FLAGS: Flags 0x%x were both set and cleared", flagsOp.set & flagsOp.clear); DWORD save = CORE.Window.flags; CORE.Window.flags |= flagsOp.set; CORE.Window.flags &= ~flagsOp.clear; - if (save != CORE.Window.flags) - { - TRACELOG(LOG_DEBUG, "DeferredFlags: 0x%x > 0x%x (diff 0x%x)", save, CORE.Window.flags, save ^ CORE.Window.flags); - } + if (save != CORE.Window.flags) TRACELOG(LOG_DEBUG, "WIN32: FLAGS: Current deferred flags: 0x%x > 0x%x (diff 0x%x)", save, CORE.Window.flags, save ^ CORE.Window.flags); return result; } static void HandleKey(WPARAM wparam, LPARAM lparam, char state) { - KeyboardKey key = KeyFromWparam(wparam); + KeyboardKey key = GetKeyFromWparam(wparam); // TODO: Use scancode? //BYTE scancode = lparam >> 16; @@ -1888,9 +2004,9 @@ static void HandleRawInput(LPARAM lparam) UINT inputSize = sizeof(input); UINT size = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &input, &inputSize, sizeof(RAWINPUTHEADER)); - if (size == (UINT)-1) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "GetRawInputData", GetLastError()); + if (size == (UINT)-1) TRACELOG(LOG_ERROR, "WIN32: Failed to get raw input data [ERROR: %lu]", GetLastError()); - if (input.header.dwType != RIM_TYPEMOUSE) TRACELOG(LOG_ERROR, "Unexpected WM_INPUT type %lu", input.header.dwType); + if (input.header.dwType != RIM_TYPEMOUSE) TRACELOG(LOG_ERROR, "WIN32: Unexpected WM_INPUT type %lu", input.header.dwType); if (input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) TRACELOG(LOG_ERROR, "TODO: handle absolute mouse inputs!"); @@ -1908,12 +2024,14 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) { if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return; - SIZE clientSize = GetClientSize(hwnd); + // Get client size (framebuffer inside the window) + RECT rect = { 0 }; + GetClientRect(hwnd, &rect); + SIZE clientSize = { rect.right, rect.bottom }; - //TRACELOG(LOG_DEBUG, "WINDOW: New widow client size: [%lux%lu]", clientSize.cx, clientSize.cy); - - //CORE.Window.currentFbo.width = clientSize.cx; - //CORE.Window.currentFbo.height = clientSize.cy; + // TODO: Update framebuffer on resize + CORE.Window.currentFbo.width = (int)clientSize.cx; + CORE.Window.currentFbo.height = (int)clientSize.cy; //glViewport(0, 0, clientSize.cx, clientSize.cy); //SetupFramebuffer(0, 0); @@ -1928,7 +2046,7 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) if (AdoptWindowResize(CORE.Window.flags)) { - TRACELOG(LOG_DEBUG, "WINDOW: Updating app size to %ix%i from window resize", screenWidth, screenHeight); + TRACELOG(LOG_DEBUG, "WIN32: WINDOW: Updating app size to [%ix%i] from window resize", screenWidth, screenHeight); *width = screenWidth; *height = screenHeight; } @@ -1951,15 +2069,21 @@ static void UpdateWindowStyle(HWND hwnd, unsigned desiredFlags) DWORD previous = STYLE_MASK_WRITABLE & SetWindowLongPtrW(hwnd, GWL_STYLE, desired); if (previous != current) { - TRACELOG(LOG_ERROR, "SetWindowLong returned writable flags 0x%x but expected 0x%x (diff=0x%x, error=%lu)", + TRACELOG(LOG_ERROR, "WIN32: WINDOW: SetWindowLongPtr() returned writable flags 0x%x but expected 0x%x (diff=0x%x, error=%lu)", previous, current, previous ^ current, GetLastError()); } CheckFlags("UpdateWindowStyle", hwnd, desiredFlags, desired, STYLE_MASK_WRITABLE); } - Mized currentMized = MizedFromStyle(MakeWindowStyle(CORE.Window.flags)); - Mized desiredMized = MizedFromStyle(MakeWindowStyle(desiredFlags)); + // Minimized takes precedence over maximized + Mized currentMized = MIZED_NONE; + Mized desiredMized = MIZED_NONE; + if (CORE.Window.flags & WS_MINIMIZE) currentMized = MIZED_MIN; + else if (CORE.Window.flags & WS_MAXIMIZE) currentMized = MIZED_MAX; + if (desiredFlags & WS_MINIMIZE) currentMized = MIZED_MIN; + else if (desiredFlags & WS_MAXIMIZE) currentMized = MIZED_MAX; + if (currentMized != desiredMized) { switch (desiredMized) @@ -1972,24 +2096,21 @@ static void UpdateWindowStyle(HWND hwnd, unsigned desiredFlags) } // Sanitize flags -static unsigned SanitizeFlags(SanitizeFlagsKind kind, unsigned flags) +static unsigned SanitizeFlags(int mode, unsigned flags) { if ((flags & FLAG_WINDOW_MAXIMIZED) && (flags & FLAG_BORDERLESS_WINDOWED_MODE)) { - TRACELOG(LOG_INFO, "borderless windows mode is overriding maximized"); + TRACELOG(LOG_WARNING, "WIN32: WINDOW: Borderless windows mode overriding maximized window flag"); flags &= ~FLAG_WINDOW_MAXIMIZED; } - switch (kind) + if (mode == 1) { - case SANITIZE_FLAGS_FIRST: break; - case SANITIZE_FLAGS_NORMAL: - if ((flags & FLAG_MSAA_4X_HINT) && (!(CORE.Window.flags & FLAG_MSAA_4X_HINT))) - { - TRACELOG(LOG_WARNING, "WINDOW: MSAA can only be configured before window initialization"); - flags &= ~FLAG_MSAA_4X_HINT; - } - break; + if ((flags & FLAG_MSAA_4X_HINT) && (!(CORE.Window.flags & FLAG_MSAA_4X_HINT))) + { + TRACELOG(LOG_WARNING, "WIN32: WINDOW: MSAA can only be configured before window initialization"); + flags &= ~FLAG_MSAA_4X_HINT; + } } return flags; @@ -2018,16 +2139,15 @@ static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height) CORE.Window.flags |= (desiredFlags & FLAG_MASK_NO_UPDATE); int vsync = (CORE.Window.flags & FLAG_VSYNC_HINT)? 1 : 0; - PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); - if (wglSwapInterval) + if (wglSwapIntervalEXT) { - (*wglSwapInterval)(vsync); + (*wglSwapIntervalEXT)(vsync); if (vsync) CORE.Window.flags |= FLAG_VSYNC_HINT; else CORE.Window.flags &= ~FLAG_VSYNC_HINT; } // TODO: Review all this code... - DWORD previousStyle; + DWORD previousStyle = 0; for (unsigned attempt = 1; ; attempt++) { CheckFlags("UpdateFlags", hwnd, CORE.Window.flags, MakeWindowStyle(CORE.Window.flags), STYLE_MASK_ALL); @@ -2035,15 +2155,14 @@ static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height) bool windowSizeUpdated = false; if (MakeWindowStyle(CORE.Window.flags) == MakeWindowStyle(desiredFlags)) { - windowSizeUpdated = UpdateWindowSize(UPDATE_WINDOW_NORMAL, hwnd, width, height, desiredFlags); + windowSizeUpdated = UpdateWindowSize(1, hwnd, width, height, desiredFlags); if ((FLAG_MASK_REQUIRED & desiredFlags) == (FLAG_MASK_REQUIRED & CORE.Window.flags)) break; } - if ((attempt > 1) && - (previousStyle == MakeWindowStyle(CORE.Window.flags)) && - !windowSizeUpdated) + + if ((attempt > 1) && (previousStyle == MakeWindowStyle(CORE.Window.flags)) && !windowSizeUpdated) { - TRACELOG(LOG_ERROR, "WINDOW: UpdateFlags() failed after %u attempt(s) wanted 0x%x but is 0x%x (diff=0x%x)", + TRACELOG(LOG_ERROR, "WIN32: WINDOW: UpdateFlags() failed after %u attempt(s) wanted 0x%x but is 0x%x (diff=0x%x)", attempt, desiredFlags, CORE.Window.flags, desiredFlags ^ CORE.Window.flags); } @@ -2051,3 +2170,21 @@ static void UpdateFlags(HWND hwnd, unsigned desiredFlags, int width, int height) UpdateWindowStyle(hwnd, desiredFlags); } } + +// Check if OpenGL extension is available +static bool IsWglExtensionAvailable(HDC hdc, const char *extension) +{ + bool result = false; + + if (wglGetExtensionsStringARB != NULL) + { + const char *extList = wglGetExtensionsStringARB(hdc); + if (extList != NULL) + { + // Simple substring search (could use strtok or strstr) + if (strstr(extList, extension) != NULL) result = true; + } + } + + return result; +} \ No newline at end of file diff --git a/src/rlgl.h b/src/rlgl.h index f587d81a2..e6a1c9432 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -2329,6 +2329,16 @@ void rlglInit(int width, int height) RLGL.State.currentMatrix = &RLGL.State.modelview; #endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2 +#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE) + // Initialize software renderer backend + int result = swInit(width, height); + if (result == 0) + { + TRACELOG(RL_LOG_ERROR, "RLSW: Software renderer initialization failed!"); + exit(-1); + } +#endif + // Initialize OpenGL default states //---------------------------------------------------------- // Init state: Depth test @@ -2345,39 +2355,28 @@ void rlglInit(int width, int height) glFrontFace(GL_CCW); // Front face are defined counter clockwise (default) glEnable(GL_CULL_FACE); // Enable backface culling - // Init state: Cubemap seamless -#if defined(GRAPHICS_API_OPENGL_33) - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Seamless cubemaps (not supported on OpenGL ES 2.0) -#endif - #if defined(GRAPHICS_API_OPENGL_11) // Init state: Color hints (deprecated in OpenGL 3.0+) glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) #endif - -#if defined(GRAPHICS_API_OPENGL_11_SOFTWARE) - int result = swInit(width, height); // Initialize software renderer backend - if (result == 0) - { - TRACELOG(RL_LOG_ERROR, "RLSW: Software renderer initialization failed!"); - exit(-1); - } +#if defined(GRAPHICS_API_OPENGL_33) + // Init state: Cubemap seamless + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Seamless cubemaps (not supported on OpenGL ES 2.0) #endif - #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Store screen size into global variables RLGL.State.framebufferWidth = width; RLGL.State.framebufferHeight = height; - - TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully"); - //---------------------------------------------------------- #endif // Init state: Color/Depth buffers clear glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black) glClearDepth(1.0f); // Set clear depth value (default) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D) + + TRACELOG(RL_LOG_INFO, "RLGL: Default OpenGL state initialized successfully"); + //---------------------------------------------------------- } // Vertex Buffer Object deinitialization (memory free) From 79b7cd6b9bfa193aa920cc7dfca64e3822e2884a Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Oct 2025 10:08:36 +0200 Subject: [PATCH 053/102] Format tweaks --- src/external/rlsw.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 49050f848..904bf1210 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -6,7 +6,7 @@ * rlsw is a custom OpenGL 1.1-style implementation on software, intended to provide all * functionality available on rlgl.h library used by raylib, becoming a direct software * rendering replacement for OpenGL 1.1 backend and allowing to run raylib on GPU-less -* devices when required. +* devices when required * * FEATURES: * - Rendering to custom internal framebuffer with multiple color modes supported: @@ -2892,8 +2892,8 @@ static inline bool sw_quad_is_axis_aligned(void) float dx = v1[0] - v0[0]; float dy = v1[1] - v0[1]; - if (fabsf(dx) > 1e-6f && fabsf(dy) < 1e-6f) horizontal++; - else if (fabsf(dy) > 1e-6f && fabsf(dx) < 1e-6f) vertical++; + if ((fabsf(dx) > 1e-6f) && (fabsf(dy) < 1e-6f)) horizontal++; + else if ((fabsf(dy) > 1e-6f) && (fabsf(dx) < 1e-6f)) vertical++; else return false; // Diagonal edge -> not axis-aligned } @@ -2933,8 +2933,8 @@ static inline void sw_quad_sort_cw(const sw_vertex_t* *output) // Separate vertices based on Y-coordinate for (int i = 0; i < 4; i++) { - if (input[i].screen[1] == minY && topCount < 2) top[topCount++] = &input[i]; - else if (input[i].screen[1] == maxY && bottomCount < 2) bottom[bottomCount++] = &input[i]; + if ((input[i].screen[1] == minY) && (topCount < 2)) top[topCount++] = &input[i]; + else if ((input[i].screen[1] == maxY) && (bottomCount < 2)) bottom[bottomCount++] = &input[i]; } // If we don't have enough top/bottom vertices (e.g., Y values are all different), @@ -2960,7 +2960,7 @@ static inline void sw_quad_sort_cw(const sw_vertex_t* *output) } // Sort bottom vertices by X (left to right) - if (bottomCount == 2 && bottom[0]->screen[0] > bottom[1]->screen[0]) + if ((bottomCount == 2) && (bottom[0]->screen[0] > bottom[1]->screen[0])) { const sw_vertex_t *temp = bottom[0]; bottom[0] = bottom[1]; @@ -2997,7 +2997,7 @@ static inline void FUNC_NAME(void) int width = xMax - xMin; \ int height = yMax - yMin; \ \ - if (width == 0 || height == 0) return; \ + if ((width == 0) || (height == 0)) return; \ \ float wRcp = (width > 0.0f)? 1.0f/width : 0.0f; \ float hRcp = (height > 0.0f)? 1.0f/height : 0.0f; \ @@ -3157,7 +3157,7 @@ static inline void sw_quad_render(void) if (RLSW.vertexCounter < 3) return; - if (RLSW.vertexCounter == 4 && sw_quad_is_axis_aligned()) + if ((RLSW.vertexCounter == 4) && sw_quad_is_axis_aligned()) { if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND(); else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_DEPTH_BLEND(); @@ -3304,7 +3304,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ int dy = y2 - y1; \ \ /* Handling of lines that are more horizontal or vertical */ \ - if (dx == 0 && dy == 0) \ + if ((dx == 0) && (dy == 0)) \ { \ /* TODO: A point should be rendered here */ \ return; \ @@ -3444,7 +3444,7 @@ void FUNC_NAME(const sw_vertex_t *v1, const sw_vertex_t *v2) \ \ RASTER_FUNC(v1, v2); \ \ - if (dx != 0 && abs(dy/dx) < 1) \ + if ((dx != 0) && (abs(dy/dx) < 1)) \ { \ int wy = (int)((RLSW.lineWidth - 1.0f)*abs(dx)/sqrtf(dx*dx + dy*dy)); \ wy >>= 1; \ @@ -3551,13 +3551,13 @@ static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \ { \ if (CHECK_BOUNDS == 1) \ { \ - if (x < RLSW.vpMin[0] || x >= RLSW.vpMax[0]) return; \ - if (y < RLSW.vpMin[1] || y >= RLSW.vpMax[1]) return; \ + if ((x < RLSW.vpMin[0]) || (x >= RLSW.vpMax[0])) return; \ + if ((y < RLSW.vpMin[1]) || (y >= RLSW.vpMax[1])) return; \ } \ else if (CHECK_BOUNDS == SW_SCISSOR_TEST) \ { \ - if (x < RLSW.scMin[0] || x >= RLSW.scMax[0]) return; \ - if (y < RLSW.scMin[1] || y >= RLSW.scMax[1]) return; \ + if ((x < RLSW.scMin[0]) || (x >= RLSW.scMax[0])) return; \ + if ((y < RLSW.scMin[1]) || (y >= RLSW.scMax[1])) return; \ } \ \ int offset = y*RLSW.framebuffer.width + x; \ @@ -3718,12 +3718,12 @@ static inline bool sw_is_texture_valid(uint32_t id) static inline bool sw_is_texture_filter_valid(int filter) { - return (filter == SW_NEAREST || filter == SW_LINEAR); + return ((filter == SW_NEAREST) || (filter == SW_LINEAR)); } static inline bool sw_is_texture_wrap_valid(int wrap) { - return (wrap == SW_REPEAT || wrap == SW_CLAMP); + return ((wrap == SW_REPEAT) || (wrap == SW_CLAMP)); } static inline bool sw_is_draw_mode_valid(int mode) @@ -4392,7 +4392,7 @@ void swRotatef(float angle, float x, float y, float z) float lengthSq = x*x + y*y + z*z; - if (lengthSq != 1.0f && lengthSq != 0.0f) + if ((lengthSq != 1.0f) && (lengthSq != 0.0f)) { float invLength = 1.0f/sqrtf(lengthSq); x *= invLength; From 3c5b3f1c1737cc20940f41ec338669d8b032abdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robin=20=E2=9D=A4=EF=B8=8F?= Date: Tue, 21 Oct 2025 04:11:19 -0400 Subject: [PATCH 054/102] [examples] Added `shapes_lines_drawing` (#5283) * Added shapes_lines_drawing Example * store result of clamp * conventions * fixed more brackets * buffer comments --- examples/shapes/shapes_lines_drawing.c | 146 +++++++++++++++++++++++ examples/shapes/shapes_lines_drawing.png | Bin 0 -> 34456 bytes 2 files changed, 146 insertions(+) create mode 100644 examples/shapes/shapes_lines_drawing.c create mode 100644 examples/shapes/shapes_lines_drawing.png diff --git a/examples/shapes/shapes_lines_drawing.c b/examples/shapes/shapes_lines_drawing.c new file mode 100644 index 000000000..9347acaf3 --- /dev/null +++ b/examples/shapes/shapes_lines_drawing.c @@ -0,0 +1,146 @@ +/******************************************************************************************* +* +* raylib [shapes] example - lines drawing +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6 +* +* Example contributed by Robin (@RobinsAviary) 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) 2025-2025 Robin (@RobinsAviary) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - lines drawing"); + + // Hint text that shows before you click the screen + bool startText = true; + + // The mouse's position on the previous frame + Vector2 mousePositionPrevious = GetMousePosition(); + + // The canvas to draw lines on + RenderTexture canvas = LoadRenderTexture(screenWidth, screenHeight); + + // The background color of the canvas + const Color backgroundColor = RAYWHITE; + + // The line's thickness + float lineThickness = 8.0f; + // The lines hue (in HSV, from 0-360) + float lineHue = 0.0f; + + // Clear the canvas to the background color + BeginTextureMode(canvas); + ClearBackground(backgroundColor); + EndTextureMode(); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Disable the hint text once the user clicks + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && startText) + { + startText = false; + } + + // Clear the canvas when the user middle-clicks + if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) + { + BeginTextureMode(canvas); + ClearBackground(backgroundColor); + EndTextureMode(); + } + + // Store whether the left and right buttons are down + bool leftButtonDown = IsMouseButtonDown(MOUSE_BUTTON_LEFT); + bool rightButtonDown = IsMouseButtonDown(MOUSE_BUTTON_RIGHT); + + if (leftButtonDown || rightButtonDown) + { + // The color for the line + Color drawColor; + + if (leftButtonDown) + { + // Increase the hue value by the distance our cursor has moved since the last frame (divided by 3) + lineHue += Vector2Distance(mousePositionPrevious, GetMousePosition())/3.0f; + + // While the hue is >=360, subtract it to bring it down into the range 0-360 + // This is more visually accurate than resetting to zero + while (lineHue >= 360.0f) + { + lineHue -= 360.0f; + } + + // Create the final color + drawColor = ColorFromHSV(lineHue, 1.0f, 1.0f); + } + else if (rightButtonDown) + { + // Use the background color as an "eraser" + drawColor = backgroundColor; + } + + // Draw the line onto the canvas + BeginTextureMode(canvas); + // Circles act as "caps", smoothing corners + DrawCircleV(mousePositionPrevious, lineThickness/2.0f, drawColor); + DrawCircleV(GetMousePosition(), lineThickness/2.0f, drawColor); + DrawLineEx(mousePositionPrevious, GetMousePosition(), lineThickness, drawColor); + EndTextureMode(); + } + + // Update line thickness based on mousewheel + lineThickness += GetMouseWheelMove(); + lineThickness = Clamp(lineThickness, 1.0, 500.0f); + + // Update mouse's previous position + mousePositionPrevious = GetMousePosition(); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + // Draw the render texture to the screen, flipped vertically to make it appear top-side up + DrawTextureRec(canvas.texture, (Rectangle){ 0.0f, 0.0f, (float)canvas.texture.width,(float)-canvas.texture.height }, Vector2Zero(), WHITE); + + // Draw the preview circle + if (!leftButtonDown) DrawCircleLinesV(GetMousePosition(), lineThickness/2.0f, (Color){ 127, 127, 127, 127 }); + + // Draw the hint text + if (startText) DrawText("try clicking and dragging!", 275, 215, 20, LIGHTGRAY); + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + // Unload the canvas render texture + UnloadRenderTexture(canvas); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_lines_drawing.png b/examples/shapes/shapes_lines_drawing.png new file mode 100644 index 0000000000000000000000000000000000000000..59ef6593439152c128657ecacb80cc91eb146e07 GIT binary patch literal 34456 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 kF$+pWf-K*!Pz?Wz1&~ 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 literal 0 HcmV?d00001 From ec06f9be371abff097c2426e8a39c358051ff397 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Oct 2025 13:51:03 +0200 Subject: [PATCH 055/102] Removed trailing spaces --- .github/workflows/build_windows.yml | 12 +-- examples/core/core_3d_camera_first_person.c | 1 - examples/core/core_render_texture.c | 16 ++-- examples/core/core_text_file_loading.c | 10 +-- examples/shapes/shapes_simple_particles.c | 8 +- src/platforms/rcore_android.c | 2 +- src/platforms/rcore_desktop_glfw.c | 7 +- src/platforms/rcore_desktop_rgfw.c | 12 +-- src/platforms/rcore_desktop_win32.c | 84 ++++++++++----------- src/platforms/rcore_drm.c | 14 ++-- src/rcore.c | 4 +- src/rtext.c | 6 +- tools/rexm/rexm.c | 8 +- 13 files changed, 91 insertions(+), 93 deletions(-) diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index 9e87b5870..7a92c208a 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -40,10 +40,10 @@ jobs: ziptarget: "win64" - compiler: msvc16 ARCH: "x86" - VSARCHPATH: "Win32" + VSARCHPATH: "Win32" ziptarget: "win32" - compiler: msvc16 - ARCH: "x64" + ARCH: "x64" VSARCHPATH: "x64" ziptarget: "win64" - compiler: msvc16 @@ -61,7 +61,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@master - + - name: Setup Release Version run: | echo "RELEASE_NAME=raylib-${{ github.event.release.tag_name }}_${{ matrix.ziptarget }}_${{ matrix.compiler }}" >> $GITHUB_ENV @@ -69,7 +69,7 @@ jobs: if: github.event_name == 'release' && github.event.action == 'published' - name: Setup Environment - run: | + run: | dir mkdir build cd build @@ -98,7 +98,7 @@ jobs: if: | matrix.compiler == 'mingw-w64' && matrix.arch == 'i686' - + - name: Build Library (MinGW-w64 64bit) run: | cd src @@ -144,7 +144,7 @@ jobs: with: name: ${{ env.RELEASE_NAME }}.zip path: ./build/${{ env.RELEASE_NAME }}.zip - + - name: Upload Artifact to Release uses: softprops/action-gh-release@v1 with: diff --git a/examples/core/core_3d_camera_first_person.c b/examples/core/core_3d_camera_first_person.c index 8f4dc70fb..64368c4aa 100644 --- a/examples/core/core_3d_camera_first_person.c +++ b/examples/core/core_3d_camera_first_person.c @@ -119,7 +119,6 @@ int main(void) // Some default standard keyboard/mouse inputs are hardcoded to simplify use // For advanced camera controls, it's recommended to compute camera movement manually UpdateCamera(&camera, cameraMode); // Update camera - /* // Camera PRO usage example (EXPERIMENTAL) // This new camera function allows custom movement/rotation values to be directly provided diff --git a/examples/core/core_render_texture.c b/examples/core/core_render_texture.c index 47dc66e0f..e30220a73 100644 --- a/examples/core/core_render_texture.c +++ b/examples/core/core_render_texture.c @@ -26,7 +26,7 @@ int main(void) const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - render texture"); - + // Define a render texture to render int renderTextureWidth = 300; int renderTextureHeight = 300; @@ -62,14 +62,14 @@ int main(void) //----------------------------------------------------- // Draw our scene to the render texture BeginTextureMode(target); - + ClearBackground(SKYBLUE); - + DrawRectangle(0, 0, 20, 20, RED); DrawCircleV(ballPosition, (float)ballRadius, MAROON); - + EndTextureMode(); - + // Draw render texture to main framebuffer BeginDrawing(); @@ -77,14 +77,14 @@ int main(void) // Draw our render texture with rotation applied // NOTE 1: We set the origin of the texture to the center of the render texture - // NOTE 2: We flip vertically the texture setting negative source rectangle height - DrawTexturePro(target.texture, + // NOTE 2: We flip vertically the texture setting negative source rectangle height + DrawTexturePro(target.texture, (Rectangle){ 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Rectangle){ screenWidth/2.0f, screenHeight/2.0f, (float)target.texture.width, (float)target.texture.height }, (Vector2){ target.texture.width/2.0f, target.texture.height/2.0f }, rotation, WHITE); DrawText("DRAWING BOUNCING BALL INSIDE RENDER TEXTURE!", 10, screenHeight - 40, 20, BLACK); - + DrawFPS(10, 10); diff --git a/examples/core/core_text_file_loading.c b/examples/core/core_text_file_loading.c index 4b334e811..033fd4dc6 100644 --- a/examples/core/core_text_file_loading.c +++ b/examples/core/core_text_file_loading.c @@ -64,7 +64,7 @@ int main(void) if (lines[i][j] == ' ') { // Making a C Style string by adding a '\0' at the required location so that we can use the MeasureText function - lines[i][j] = '\0'; + lines[i][j] = '\0'; // Checking if the text has crossed the wrapWidth, then going back and inserting a newline if (MeasureText(lines[i] + lastWrapStart, fontSize) > wrapWidth) @@ -112,8 +112,8 @@ int main(void) cam.target.y -= scroll*fontSize*1.5f; // Choosing an arbitrary speed for scroll if (cam.target.y < 0) cam.target.y = 0; // Snapping to 0 if we go too far back - - // Ensuring that the camera does not scroll past all text + + // Ensuring that the camera does not scroll past all text if (cam.target.y > textHeight - screenHeight + textTop) cam.target.y = textHeight - screenHeight + textTop; @@ -133,10 +133,10 @@ int main(void) { // Each time we go through and calculate the height of the text to move the cursor appropriately Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); - + DrawText(lines[i], 10, t, fontSize, RED); - // Inserting extra space for real newlines, + // Inserting extra space for real newlines, // wrapped lines are rendered closer together t += size.y + 10; } diff --git a/examples/shapes/shapes_simple_particles.c b/examples/shapes/shapes_simple_particles.c index 7c2a598c2..c5d9612c3 100644 --- a/examples/shapes/shapes_simple_particles.c +++ b/examples/shapes/shapes_simple_particles.c @@ -74,7 +74,7 @@ int main(void) // Definition of particles Particle *particles = (Particle*)RL_CALLOC(MAX_PARTICLES, sizeof(Particle)); // Particle array CircularBuffer circularBuffer = { 0, 0, particles }; - + // Particle emitter parameters int emissionRate = -2; // Negative: on average every -X frames. Positive: particles per frame ParticleType currentType = WATER; @@ -100,7 +100,7 @@ int main(void) // Update the parameters of each particle UpdateParticles(&circularBuffer, screenWidth, screenHeight); - + // Remove dead particles from the circular buffer UpdateCircularBuffer(&circularBuffer); @@ -252,10 +252,10 @@ static void UpdateParticles(CircularBuffer *circularBuffer, int screenWidth, int // Disable particle when out of screen Vector2 center = circularBuffer->buffer[i].position; float radius = circularBuffer->buffer[i].radius; - + if ((center.x < -radius) || (center.x > (screenWidth + radius)) || (center.y < -radius) || (center.y > (screenHeight + radius))) - { + { circularBuffer->buffer[i].alive = false; } } diff --git a/src/platforms/rcore_android.c b/src/platforms/rcore_android.c index 6ecc41888..47dcce32b 100644 --- a/src/platforms/rcore_android.c +++ b/src/platforms/rcore_android.c @@ -461,7 +461,7 @@ int GetCurrentMonitor(void) if (display == NULL) { TRACELOG(LOG_ERROR, "GetCurrentMonitor() couldn't get the display object"); - } + } else { jclass displayClass = (*env)->FindClass(env, "android/view/Display"); diff --git a/src/platforms/rcore_desktop_glfw.c b/src/platforms/rcore_desktop_glfw.c index 729ca308c..5dde1df67 100644 --- a/src/platforms/rcore_desktop_glfw.c +++ b/src/platforms/rcore_desktop_glfw.c @@ -1048,6 +1048,7 @@ Image GetClipboardImage(void) void ShowCursor(void) { glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + CORE.Input.Mouse.cursorHidden = false; } @@ -1055,6 +1056,7 @@ void ShowCursor(void) void HideCursor(void) { glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + CORE.Input.Mouse.cursorHidden = true; } @@ -1075,13 +1077,10 @@ void EnableCursor(void) void DisableCursor(void) { // Reset mouse position within the window area before disabling cursor - SetMousePosition(CORE.Window.screen.width, CORE.Window.screen.height); + SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - // Set cursor position in the middle - SetMousePosition(CORE.Window.screen.width/2, CORE.Window.screen.height/2); - if (glfwRawMouseMotionSupported()) glfwSetInputMode(platform.handle, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); CORE.Input.Mouse.cursorLocked = true; diff --git a/src/platforms/rcore_desktop_rgfw.c b/src/platforms/rcore_desktop_rgfw.c index 52ec6ac94..86842140d 100644 --- a/src/platforms/rcore_desktop_rgfw.c +++ b/src/platforms/rcore_desktop_rgfw.c @@ -80,7 +80,7 @@ void CloseWindow(void); #define CloseWindow CloseWindow_win32 #define ShowCursor __imp_ShowCursor #define _APISETSTRING_ - + #undef MAX_PATH #if defined(__cplusplus) @@ -262,7 +262,7 @@ static int RGFW_gpConvTable[18] = { [RGFW_gamepadRight] = GAMEPAD_BUTTON_LEFT_FACE_RIGHT, [RGFW_gamepadDown] = GAMEPAD_BUTTON_LEFT_FACE_DOWN, [RGFW_gamepadLeft] = GAMEPAD_BUTTON_LEFT_FACE_LEFT, - [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB, + [RGFW_gamepadL3] = GAMEPAD_BUTTON_LEFT_THUMB, [RGFW_gamepadR3] = GAMEPAD_BUTTON_RIGHT_THUMB, }; @@ -933,7 +933,7 @@ void PollInputEvents(void) // because ProcessGestureEvent() is just called on an event, not every frame UpdateGestures(); #endif - + // Reset keys/chars pressed registered CORE.Input.Keyboard.keyPressedQueueCount = 0; CORE.Input.Keyboard.charPressedQueueCount = 0; @@ -1025,7 +1025,7 @@ void PollInputEvents(void) CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); strcpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event->droppedFiles[i]); - + CORE.Window.dropFileCount++; } else if (CORE.Window.dropFileCount < 1024) @@ -1229,7 +1229,7 @@ void PollInputEvents(void) int button = (axis == GAMEPAD_AXIS_LEFT_TRIGGER)? GAMEPAD_BUTTON_LEFT_TRIGGER_2 : GAMEPAD_BUTTON_RIGHT_TRIGGER_2; int pressed = (value > 0.1f); CORE.Input.Gamepad.currentButtonState[event->gamepad][button] = pressed; - + if (pressed) CORE.Input.Gamepad.lastButtonPressed = button; else if (CORE.Input.Gamepad.lastButtonPressed == button) CORE.Input.Gamepad.lastButtonPressed = 0; } @@ -1345,7 +1345,7 @@ int InitPlatform(void) // TODO: Is this needed by raylib now? // If so, rcore_desktop_sdl should be updated too //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_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 7ac6138bd..de9a66911 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -84,8 +84,8 @@ // Types and Structures Definition //---------------------------------------------------------------------------------- -// NOTE: appScreenSize is the last screen size requested by the app, -// the backend must keep the client area this size (after DPI scaling is applied) +// NOTE: appScreenSize is the last screen size requested by the app, +// the backend must keep the client area this size (after DPI scaling is applied) // when the window isn't fullscreen/maximized/minimized typedef struct { HWND hwnd; // Window handler @@ -141,7 +141,7 @@ static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL; AToWCopy(inAnsi, outWstr, outLen); \ outWstr[outLen] = 0; \ } while (0) - + #define STYLE_MASK_ALL 0xffffffff #define STYLE_MASK_READONLY (WS_MINIMIZE | WS_MAXIMIZE) #define STYLE_MASK_WRITABLE (~STYLE_MASK_READONLY) @@ -206,10 +206,10 @@ static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL; // Types and Structures Definition //---------------------------------------------------------------------------------- // Maximize-minimize request types -typedef enum { - MIZED_NONE, - MIZED_MIN, - MIZED_MAX +typedef enum { + MIZED_NONE, + MIZED_MIN, + MIZED_MAX } Mized; // Flag operations @@ -234,7 +234,7 @@ typedef struct { static size_t AToWLen(const char *ascii) { int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, ascii, -1, NULL, 0); - + if (sizeNeeded < 0) TRACELOG(LOG_ERROR, "WIN32: Failed to calculate wide length [ERROR: %u]", GetLastError()); return sizeNeeded; @@ -268,7 +268,7 @@ static DWORD MakeWindowStyle(unsigned flags) // it improves efficiency, plus, windows adds this flag automatically anyway // so it keeps our flags in sync with the OS DWORD style = WS_CLIPSIBLINGS; - + style |= (flags & FLAG_WINDOW_HIDDEN)? 0 : WS_VISIBLE; style |= (flags & FLAG_WINDOW_RESIZABLE)? STYLE_FLAGS_RESIZABLE : 0; style |= (flags & FLAG_WINDOW_UNDECORATED)? STYLE_FLAGS_UNDECORATED_ON : STYLE_FLAGS_UNDECORATED_OFF; @@ -339,7 +339,7 @@ static void CheckFlags(const char *context, HWND hwnd, DWORD flags, DWORD expect static SIZE CalcWindowSize(UINT dpi, SIZE clientSize, DWORD style) { RECT rect = { 0, 0, clientSize.cx, clientSize.cy }; - + int result = AdjustWindowRectExForDpi(&rect, style, 0, WINDOW_STYLE_EX, dpi); if (result == 0) TRACELOG(LOG_ERROR, "WIN32: Failed to adjust window rect [ERROR: %lu]", GetLastError()); @@ -442,8 +442,8 @@ static bool UpdateWindowSize(int mode, HWND hwnd, int width, int height, unsigne static BOOL IsWindows10Version1703OrGreaterWin32(void) { HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); - - DWORD (*Verify)(RTL_OSVERSIONINFOEXW*, ULONG, ULONGLONG) = + + DWORD (*Verify)(RTL_OSVERSIONINFOEXW*, ULONG, ULONGLONG) = (DWORD (*)(RTL_OSVERSIONINFOEXW*, ULONG, ULONGLONG))GetProcAddress(ntdll, "RtlVerifyVersionInfo"); if (!Verify) { @@ -461,7 +461,7 @@ static BOOL IsWindows10Version1703OrGreaterWin32(void) VER_SET_CONDITION(cond, VER_MAJORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION(cond, VER_MINORVERSION, VER_GREATER_EQUAL); VER_SET_CONDITION(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL); - + return 0 == (*Verify)(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, cond); } @@ -473,8 +473,8 @@ static void *WglGetProcAddress(const char *procname) if ((proc == NULL) || // NOTE: Some GPU drivers could return following // invalid sentinel values instead of NULL - (proc == (void *)0x1) || - (proc == (void *)0x2) || + (proc == (void *)0x1) || + (proc == (void *)0x2) || (proc == (void *)0x3) || (proc == (void *)-1)) { @@ -767,7 +767,7 @@ static void GetStyleChangeFlagOps(DWORD coreWindowFlags, STYLESTRUCT *style, Fla } // Adopt window resize -// NOTE: Call when the window is rezised, returns true +// NOTE: Call when the window is rezised, returns true // if the new window size should update the desired app size static bool AdoptWindowResize(unsigned flags) { @@ -776,7 +776,7 @@ static bool AdoptWindowResize(unsigned flags) if (flags & FLAG_FULLSCREEN_MODE) return false; if (flags & FLAG_BORDERLESS_WINDOWED_MODE) return false; if (!(flags & FLAG_WINDOW_RESIZABLE)) return false; - + return true; } @@ -947,10 +947,10 @@ void SetWindowIcons(Image *images, int count) void SetWindowTitle(const char *title) { CORE.Window.title = title; - + WCHAR *titleWide = NULL; A_TO_W_ALLOCA(titleWide, CORE.Window.title); - + int result = SetWindowTextW(platform.hwnd, titleWide); if (result == 0) TRACELOG(LOG_WARNING, "WIN32: Failed to set window title [ERROR: %lu]", GetLastError()); } @@ -1023,7 +1023,7 @@ void *GetWindowHandle(void) int GetMonitorCount(void) { int count = 0; - + int result = EnumDisplayMonitors(NULL, NULL, CountMonitorsProc, (LPARAM)&count); if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "EnumDisplayMonitors", GetLastError()); @@ -1040,7 +1040,7 @@ int GetCurrentMonitor(void) info.needle = monitor; info.index = 0; info.matchIndex = -1; - + int result = EnumDisplayMonitors(NULL, NULL, FindMonitorProc, (LPARAM)&info); if (result == 0) TRACELOG(LOG_ERROR, "%s failed, error=%lu", "EnumDisplayMonitors", GetLastError()); @@ -1127,7 +1127,7 @@ const char *GetClipboardText(void) Image GetClipboardImage(void) { Image image = { 0 }; - + TRACELOG(LOG_WARNING, "GetClipboardText not implemented"); return image; @@ -1193,7 +1193,7 @@ void DisableCursor(void) TRACELOG(LOG_INFO, "WIN32: Clip cursor client rect: [%d,%d %d,%d], top-left: (%d,%d)", clientRect.left, clientRect.top, clientRect.right, clientRect.bottom, topleft.x, topleft.y); - + LONG centerX = topleft.x + width/2; LONG centerY = topleft.y + height/2; RECT clipRect = { centerX, centerY, centerX + 1, centerY + 1 }; @@ -1502,7 +1502,7 @@ int InitPlatform(void) if (IsWindows10Version1703OrGreaterWin32()) { TRACELOG(LOG_INFO, "DpiAware: >=Win10Creators"); - if (!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) + if (!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) TRACELOG(LOG_ERROR, "%s failed, error %u", "SetProcessDpiAwarenessContext", GetLastError()); } else @@ -1620,7 +1620,7 @@ int InitPlatform(void) } CORE.Window.ready = true; - + // TODO: Should this function be called before or after drawing context is created? --> After swInit() called! //UpdateWindowSize(UPDATE_WINDOW_FIRST, platform.hwnd, platform.appScreenWidth, platform.appScreenHeight, platform.desiredFlags); UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight); @@ -1660,7 +1660,7 @@ int InitPlatform(void) //---------------------------------------------------------------------------- TRACELOG(LOG_INFO, "PLATFORM: DESKTOP: WIN32: Initialized successfully"); - + return 0; } @@ -1691,7 +1691,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara FlagsOp flagsOp = { 0 }; FlagsOp *deferredFlags = &flagsOp; - + // Message processing //------------------------------------------------------------------------------------ switch (msg) @@ -1707,13 +1707,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara // Clean up for window destruction if (rlGetVersion() == RL_OPENGL_11_SOFTWARE) // Using software renderer { - if (platform.hdcmem) + if (platform.hdcmem) { DeleteDC(platform.hdcmem); platform.hdcmem = NULL; } - if (platform.hbitmap) + if (platform.hbitmap) { DeleteObject(platform.hbitmap); // Clears platform.pixels data platform.hbitmap = NULL; @@ -1751,9 +1751,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara if (CORE.Window.flags & FLAG_WINDOW_RESIZABLE) { // TODO: Enforce min/max size - } + } else TRACELOG(LOG_WARNING, "WIN32: WINDOW: Trying to resize a non-resizable window"); - + result = TRUE; } break; case WM_STYLECHANGING: @@ -1770,11 +1770,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara SIZE clientSize = { rect.right, rect.bottom }; SIZE oldSize = CalcWindowSize(dpi, clientSize, ss->styleOld); SIZE newSize = CalcWindowSize(dpi, clientSize, ss->styleNew); - + if (oldSize.cx != newSize.cx || oldSize.cy != newSize.cy) { TRACELOG(LOG_INFO, "WIN32: WINDOW: Resize from style change [%dx%d] to [%dx%d]", oldSize.cx, oldSize.cy, newSize.cx, newSize.cy); - + if (CORE.Window.flags & FLAG_WINDOW_MAXIMIZED) { // looks like windows will automatically "unminimize" a window @@ -1795,7 +1795,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara bool isIconic = IsIconic(hwnd); bool styleMinimized = !!(WS_MINIMIZE & GetWindowLongPtrW(hwnd, GWL_STYLE)); if (isIconic != styleMinimized) TRACELOG(LOG_WARNING, "WIN32: IsIconic state different from WS_MINIMIZED state"); - + if (isIconic) mized = MIZED_MIN; else { @@ -1871,7 +1871,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara }; inoutSize->cx = desired.cx; inoutSize->cy = desired.cy; - + result = TRUE; } break; case WM_DPICHANGED: @@ -1929,7 +1929,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara case WM_RBUTTONUP : HandleMouseButton(MOUSE_BUTTON_RIGHT, 0); break; case WM_MBUTTONDOWN: HandleMouseButton(MOUSE_BUTTON_MIDDLE, 1); break; case WM_MBUTTONUP : HandleMouseButton(MOUSE_BUTTON_MIDDLE, 0); break; - case WM_XBUTTONDOWN: + case WM_XBUTTONDOWN: { switch (HIWORD(wparam)) { @@ -1975,11 +1975,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara static void HandleKey(WPARAM wparam, LPARAM lparam, char state) { KeyboardKey key = GetKeyFromWparam(wparam); - + // TODO: Use scancode? //BYTE scancode = lparam >> 16; //TRACELOG(LOG_INFO, "KEY key=%d vk=%lu scan=%u = %u", key, wparam, scancode, state); - + if (key != KEY_NULL) { CORE.Input.Keyboard.currentKeyState[key] = state; @@ -2003,9 +2003,9 @@ static void HandleRawInput(LPARAM lparam) UINT inputSize = sizeof(input); UINT size = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &input, &inputSize, sizeof(RAWINPUTHEADER)); - + if (size == (UINT)-1) TRACELOG(LOG_ERROR, "WIN32: Failed to get raw input data [ERROR: %lu]", GetLastError()); - + if (input.header.dwType != RIM_TYPEMOUSE) TRACELOG(LOG_ERROR, "WIN32: Unexpected WM_INPUT type %lu", input.header.dwType); if (input.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE) TRACELOG(LOG_ERROR, "TODO: handle absolute mouse inputs!"); @@ -2043,7 +2043,7 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) unsigned int screenHeight = highdpi? (unsigned int)(((float)clientSize.cy)/dpiScale) : clientSize.cy; CORE.Window.screen.width = screenWidth; CORE.Window.screen.height = screenHeight; - + if (AdoptWindowResize(CORE.Window.flags)) { TRACELOG(LOG_DEBUG, "WIN32: WINDOW: Updating app size to [%ix%i] from window resize", screenWidth, screenHeight); @@ -2062,7 +2062,7 @@ static void UpdateWindowStyle(HWND hwnd, unsigned desiredFlags) { DWORD current = STYLE_MASK_WRITABLE & MakeWindowStyle(CORE.Window.flags); DWORD desired = STYLE_MASK_WRITABLE & MakeWindowStyle(desiredFlags); - + if (current != desired) { SetLastError(0); diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index 58e820af1..a08a76bce 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -864,7 +864,7 @@ void SwapScreenBuffer(void) // Create framebuffer with the correct format uint32_t fb = 0; result = drmModeAddFB(platform.fd, width, height, depth, bpp, creq.pitch, creq.handle, &fb); - if (result != 0) + if (result != 0) { TRACELOG(LOG_ERROR, "DISPLAY: drmModeAddFB() failed with result: %d (%s)", result, strerror(errno)); struct drm_mode_destroy_dumb dreq = { 0 }; @@ -974,12 +974,12 @@ void SwapScreenBuffer(void) // Set CRTC with better error handling result = drmModeSetCrtc(platform.fd, crtcId, fb, 0, 0, &platform.connector->connector_id, 1, mode); - if (result != 0) + if (result != 0) { TRACELOG(LOG_ERROR, "DISPLAY: drmModeSetCrtc() failed with result: %d (%s)", result, strerror(errno)); TRACELOG(LOG_ERROR, "DISPLAY: CRTC ID: %u, FB ID: %u, Connector ID: %u", crtcId, fb, platform.connector->connector_id); TRACELOG(LOG_ERROR, "DISPLAY: Mode: %dx%d@%d", mode->hdisplay, mode->vdisplay, mode->vrefresh); - + drmModeRmFB(platform.fd, fb); struct drm_mode_destroy_dumb dreq = {0}; dreq.handle = creq.handle; @@ -1229,7 +1229,7 @@ int InitPlatform(void) } TRACELOG(LOG_TRACE, "DISPLAY: Connector %i modes detected: %i", i, con->count_modes); - TRACELOG(LOG_TRACE, "DISPLAY: Connector %i status: %s", i, + TRACELOG(LOG_TRACE, "DISPLAY: Connector %i status: %s", i, (con->connection == DRM_MODE_CONNECTED) ? "CONNECTED" : (con->connection == DRM_MODE_DISCONNECTED) ? "DISCONNECTED" : (con->connection == DRM_MODE_UNKNOWNCONNECTION) ? "UNKNOWN" : "OTHER"); @@ -1357,10 +1357,10 @@ int InitPlatform(void) platform.modeIndex = 0; CORE.Window.display.width = platform.connector->modes[0].hdisplay; CORE.Window.display.height = platform.connector->modes[0].vdisplay; - - TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u) for software rendering", + + TRACELOG(LOG_INFO, "DISPLAY: Selected DRM connector mode %s (%ux%u%c@%u) for software rendering", platform.connector->modes[0].name, - platform.connector->modes[0].hdisplay, + platform.connector->modes[0].hdisplay, platform.connector->modes[0].vdisplay, (platform.connector->modes[0].flags & DRM_MODE_FLAG_INTERLACE) ? 'i' : 'p', platform.connector->modes[0].vrefresh); diff --git a/src/rcore.c b/src/rcore.c index 5dea97c22..350490ad1 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -2524,7 +2524,7 @@ int MakeDirectory(const char *dirPath) // Create final directory if (!DirectoryExists(pathcpy)) MKDIR(pathcpy); RL_FREE(pathcpy); - + // In case something failed and requested directory // was not successfully created, return -1 if (!DirectoryExists(dirPath)) return -1; @@ -3148,7 +3148,7 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize) unsigned char *block = buffer + (blockN*64); unsigned int w[64]; for (int i = 0; i < 16; i++) - { + { w[i] = ((unsigned int)block[i*4 + 0] << 24) | ((unsigned int)block[i*4 + 1] << 16) | diff --git a/src/rtext.c b/src/rtext.c index 9951dc66d..b4cd560ba 100644 --- a/src/rtext.c +++ b/src/rtext.c @@ -1701,9 +1701,9 @@ char *GetTextBetween(const char *text, const char *begin, const char *end) char *TextReplace(const char *text, const char *search, const char *replacement) { char *result = NULL; - + if (!text || !search) return NULL; // Sanity check - + char *insertPoint = NULL; // Next insert point char *temp = NULL; // Temp pointer int searchLen = 0; // Search string length of (the string to remove) @@ -1753,7 +1753,7 @@ char *TextReplaceBetween(const char *text, const char *begin, const char *end, c char *result = NULL; if (!text || !begin || !end) return NULL; // Sanity check - + int beginIndex = TextFindIndex(text, begin); if (beginIndex > -1) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 20fc1d5e5..d668655c8 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -239,7 +239,7 @@ int main(int argc, char *argv[]) // build : Build example for Desktop and Web platforms // validate : Validate examples collection, generates report // update : Validate and update examples collection, generates report - + if (strcmp(argv[1], "create") == 0) { // Check for valid upcoming argument @@ -394,8 +394,8 @@ int main(int argc, char *argv[]) { // Support building not only individual examples but categories and "ALL" if ((strcmp(argv[2], "ALL") == 0) || TextInList(argv[2], exCategories, REXM_MAX_EXAMPLE_CATEGORIES)) - { - // Category/ALL rebuilt requested + { + // Category/ALL rebuilt requested strcpy(exRebuildRequested, argv[2]); } else @@ -2432,7 +2432,7 @@ static void UpdateWebMetadata(const char *exHtmlPath, const char *exFilePath) static bool TextInList(const char *text, const char **list, int listCount) { bool result = false; - + for (int i = 0; i < listCount; i++) { if (TextIsEqual(text, list[i])) { result = true; break; } From 77b9214575ec60abe6824fd7c8abf40169c8e966 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Oct 2025 20:07:32 +0200 Subject: [PATCH 056/102] Update rcore_desktop_sdl.c --- src/platforms/rcore_desktop_sdl.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index 6655db460..a5f626ecc 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -104,7 +104,6 @@ typedef struct { SDL_GameController *gamepad[MAX_GAMEPADS]; SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids, they do not start from 0 SDL_Cursor *cursor; - bool cursorRelative; } PlatformData; //---------------------------------------------------------------------------------- @@ -1209,13 +1208,13 @@ void EnableCursor(void) SDL_SetRelativeMouseMode(SDL_FALSE); #if defined(USING_VERSION_SDL3) - // SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() + // NOTE: SDL_ShowCursor() has been split into three functions: + // SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() SDL_ShowCursor(); #else SDL_ShowCursor(SDL_ENABLE); #endif - platform.cursorRelative = false; CORE.Input.Mouse.cursorLocked = false; } @@ -1224,7 +1223,6 @@ void DisableCursor(void) { SDL_SetRelativeMouseMode(SDL_TRUE); - platform.cursorRelative = true; CORE.Input.Mouse.cursorLocked = true; } @@ -1332,7 +1330,7 @@ void PollInputEvents(void) CORE.Input.Mouse.currentWheelMove.y = 0; // Register previous mouse position - if (platform.cursorRelative) CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; + if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.currentPosition = (Vector2){ 0.0f, 0.0f }; else CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition; // Reset last gamepad button/axis registered state @@ -1634,7 +1632,7 @@ void PollInputEvents(void) } break; case SDL_MOUSEMOTION: { - if (platform.cursorRelative) + if (CORE.Input.Mouse.cursorLocked) { CORE.Input.Mouse.currentPosition.x = (float)event.motion.xrel; CORE.Input.Mouse.currentPosition.y = (float)event.motion.yrel; From 99ed81461526b37583cac323a51a5d019b49b16c Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 21 Oct 2025 20:07:42 +0200 Subject: [PATCH 057/102] Update rcore_desktop_win32.c --- src/platforms/rcore_desktop_win32.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index de9a66911..9b66f8c4b 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1136,17 +1136,17 @@ Image GetClipboardImage(void) // Show mouse cursor void ShowCursor(void) { - CORE.Input.Mouse.cursorHidden = false; SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_ARROW)); + CORE.Input.Mouse.cursorHidden = false; } // Hides mouse cursor void HideCursor(void) { - // NOTE: we use SetCursor instead of ShowCursor because it makes it easy - // to only hide the cursor while it's inside the client area - CORE.Input.Mouse.cursorHidden = true; + // NOTE: We use SetCursor() instead of ShowCursor() because + // it makes it easy to only hide the cursor while it's inside the client area SetCursor(NULL); + CORE.Input.Mouse.cursorHidden = true; } // Enables cursor (unlock cursor) @@ -1346,7 +1346,7 @@ void PollInputEvents(void) //---------------------------------------------------------------------------------- // Initialize modern OpenGL context -// NOTE: We need to create a dummy context first to query requried extensions +// NOTE: We need to create a dummy context first to query required extensions HGLRC InitOpenGL(HWND hwnd, HDC hdc) { // First, create a dummy context to get WGL extensions @@ -1621,8 +1621,7 @@ int InitPlatform(void) CORE.Window.ready = true; - // TODO: Should this function be called before or after drawing context is created? --> After swInit() called! - //UpdateWindowSize(UPDATE_WINDOW_FIRST, platform.hwnd, platform.appScreenWidth, platform.appScreenHeight, platform.desiredFlags); + // Update flags (in case of deferred state change required) UpdateFlags(platform.hwnd, platform.desiredFlags, platform.appScreenWidth, platform.appScreenHeight); CORE.Window.render.width = CORE.Window.screen.width; @@ -1887,6 +1886,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara } break; case WM_SETCURSOR: { + // Called when mouse moves, enters/leaves window... if (LOWORD(lparam) == HTCLIENT) { SetCursor(CORE.Input.Mouse.cursorHidden? NULL : LoadCursorW(NULL, (LPCWSTR)IDC_ARROW)); @@ -1972,6 +1972,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara return result; } +// Handle keyboard input event static void HandleKey(WPARAM wparam, LPARAM lparam, char state) { KeyboardKey key = GetKeyFromWparam(wparam); @@ -1991,12 +1992,15 @@ static void HandleKey(WPARAM wparam, LPARAM lparam, char state) // TODO: Add key to the queue as well? } +// Handle mouse button input event static void HandleMouseButton(int button, char state) { + // Register current mouse button state CORE.Input.Mouse.currentButtonState[button] = state; CORE.Input.Touch.currentTouchState[button] = state; } +// Handle raw input event static void HandleRawInput(LPARAM lparam) { RAWINPUT input = { 0 }; @@ -2020,6 +2024,7 @@ static void HandleRawInput(LPARAM lparam) //if (CORE.Input.Mouse.currentPosition.y != 0) abort(); } +// Handle window resizing event static void HandleWindowResize(HWND hwnd, int *width, int *height) { if (CORE.Window.flags & FLAG_WINDOW_MINIMIZED) return; @@ -2051,10 +2056,8 @@ static void HandleWindowResize(HWND hwnd, int *width, int *height) *height = screenHeight; } - CORE.Window.screenScale = MatrixScale( - (float)CORE.Window.render.width/CORE.Window.screen.width, - (float)CORE.Window.render.height/CORE.Window.screen.height, - 1.0f); + CORE.Window.screenScale = MatrixScale( (float)CORE.Window.render.width/CORE.Window.screen.width, + (float)CORE.Window.render.height/CORE.Window.screen.height, 1.0f); } // Update window style From 1b5a14e5167755d54e8b4e9851b9167302641d2f Mon Sep 17 00:00:00 2001 From: sleeptightAnsiC <91839286+sleeptightAnsiC@users.noreply.github.com> Date: Tue, 21 Oct 2025 22:07:04 +0200 Subject: [PATCH 058/102] [rcore_desktop_sdl] fix: handle monitor ID correctly on SDL3 (#5290) SDL3 uses ID when dealing with monitors, unlike SDL2 which uses Index for the same thing. This problem was already fixed in multiple places by use of preprocessor branches, so I did the very same thing. Please, notice that this is a pretty bad solution to this problem, and I only did it to keep it consistent with the rest of the code. The more about why it's not correct is mentioned here: https://github.com/raysan5/raylib/issues/5256#issuecomment-3429156919 Hopefully, someone will refactor it someday :) Fixes: https://github.com/raysan5/raylib/issues/5256 --- src/platforms/rcore_desktop_sdl.c | 37 ++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index a5f626ecc..e135cd848 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -837,7 +837,11 @@ void SetWindowPosition(int x, int y) void SetWindowMonitor(int monitor) { const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { // NOTE: // 1. SDL started supporting moving exclusive fullscreen windows between displays on SDL3, @@ -961,7 +965,11 @@ int GetCurrentMonitor(void) Vector2 GetMonitorPosition(int monitor) { const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { SDL_Rect displayBounds; @@ -985,7 +993,11 @@ int GetMonitorWidth(int monitor) int width = 0; const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { SDL_DisplayMode mode; SDL_GetCurrentDisplayMode(monitor, &mode); @@ -1002,7 +1014,11 @@ int GetMonitorHeight(int monitor) int height = 0; const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { SDL_DisplayMode mode; SDL_GetCurrentDisplayMode(monitor, &mode); @@ -1019,7 +1035,11 @@ int GetMonitorPhysicalWidth(int monitor) int width = 0; const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { float ddpi = 0.0f; SDL_GetDisplayDPI(monitor, &ddpi, NULL, NULL); @@ -1039,7 +1059,11 @@ int GetMonitorPhysicalHeight(int monitor) int height = 0; const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { float ddpi = 0.0f; SDL_GetDisplayDPI(monitor, &ddpi, NULL, NULL); @@ -1059,7 +1083,11 @@ int GetMonitorRefreshRate(int monitor) int refresh = 0; const int monitorCount = SDL_GetNumVideoDisplays(); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else if ((monitor >= 0) && (monitor < monitorCount)) +#endif { SDL_DisplayMode mode; SDL_GetCurrentDisplayMode(monitor, &mode); @@ -1075,7 +1103,14 @@ const char *GetMonitorName(int monitor) { const int monitorCount = SDL_GetNumVideoDisplays(); - if ((monitor >= 0) && (monitor < monitorCount)) return SDL_GetDisplayName(monitor); +#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure + if ((monitor > 0) && (monitor <= monitorCount)) +#else + if ((monitor >= 0) && (monitor < monitorCount)) +#endif + { + return SDL_GetDisplayName(monitor); + } else TRACELOG(LOG_WARNING, "SDL: Failed to find selected monitor"); return ""; From 428421f21a565b301e24e624fd2ffb4e1727258a Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 Oct 2025 11:03:19 +0200 Subject: [PATCH 059/102] Update examples_list.txt --- examples/examples_list.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 2a1b9c0b7..71cda6c1a 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -51,6 +51,7 @@ core;core_directory_files;★☆☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal core;core_highdpi_testbed;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_screen_recording;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Ramon Santamaria";@raysan5 core;core_clipboard_text;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Robin";@RobinsAviary +core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04 shapes;shapes_basic_shapes;★☆☆☆;1.0;4.2;2014;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bouncing_ball;★☆☆☆;2.5;2.5;2013;2025;"Ramon Santamaria";@raysan5 shapes;shapes_bullet_hell;★☆☆☆;5.6;5.6;2025;2025;"Zero";@zerohorsepower @@ -160,6 +161,7 @@ shaders;shaders_texture_rendering;★★☆☆;2.0;3.7;2019;2025;"Michał Ciesie shaders;shaders_texture_outline;★★★☆;4.0;4.0;2021;2025;"Serenity Skiff";@GoldenThumbs shaders;shaders_texture_waves;★★☆☆;2.5;3.7;2019;2025;"Anata";@anatagawa shaders;shaders_julia_set;★★★☆;2.5;4.0;2019;2025;"Josh Colclough";@joshcol9232 +shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shaders;shaders_eratosthenes_sieve;★★★☆;2.5;4.0;2019;2025;"ProfJski";@ProfJski shaders;shaders_fog_rendering;★★★☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_simple_mask;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho @@ -192,5 +194,3 @@ others;easings_testbed;★★★☆;2.5;3.0;2019;2025;"Juan Miguel López";@flas others;raylib_opengl_interop;★★★★;3.8;4.0;2021;2025;"Stephan Soller";@arkanis others;embedded_files_loading;★★☆☆;3.0;3.5;2020;2025;"Kristian Holmgren";@defutura others;web_basic_window;★☆☆☆;5.6-dev;5.6-dev;2014;2025;"Ramon Santamaria";@raysan5 -core;core_text_file_loading;★☆☆☆;5.5;5.6;0;0;"Aanjishnu Bhattacharyya";@NimComPoo-04 -shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant From 780a7df760d45b8bd386be425ab5c2da0b1a48f6 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 23 Oct 2025 04:25:23 -0700 Subject: [PATCH 060/102] Fix warnings in more examples. (#5292) --- examples/core/core_text_file_loading.c | 16 ++++++++-------- examples/shapes/shapes_clock_of_clocks.c | 3 +++ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/core/core_text_file_loading.c b/examples/core/core_text_file_loading.c index 033fd4dc6..ed48f7d36 100644 --- a/examples/core/core_text_file_loading.c +++ b/examples/core/core_text_file_loading.c @@ -88,16 +88,16 @@ int main(void) for (int i = 0; i < lineCount; i++) { - Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); - textHeight += size.y + 10; + Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2); + textHeight += (int)size.y + 10; } // A simple scrollbar on the side to show how far we have red into the file Rectangle scrollBar = { - .x = screenWidth - 5, + .x = (float)screenWidth - 5, .y = 0, .width = 5, - .height = screenHeight*100/(textHeight - screenHeight) // Scrollbar height is just a percentage + .height = screenHeight*100.0f/(textHeight - screenHeight) // Scrollbar height is just a percentage }; SetTargetFPS(60); @@ -115,10 +115,10 @@ int main(void) // Ensuring that the camera does not scroll past all text if (cam.target.y > textHeight - screenHeight + textTop) - cam.target.y = textHeight - screenHeight + textTop; + cam.target.y = (float)textHeight - screenHeight + textTop; // Computing the position of the scrollBar depending on the percentage of text covered - scrollBar.y = Lerp(textTop, screenHeight - scrollBar.height, (cam.target.y - textTop)/(textHeight - screenHeight)); + scrollBar.y = Lerp((float)textTop, (float)screenHeight - scrollBar.height, (float)(cam.target.y - textTop)/(textHeight - screenHeight)); //---------------------------------------------------------------------------------- // Draw @@ -132,13 +132,13 @@ int main(void) for (int i = 0, t = textTop; i < lineCount; i++) { // Each time we go through and calculate the height of the text to move the cursor appropriately - Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], fontSize, 2); + Vector2 size = MeasureTextEx(GetFontDefault(), lines[i], (float)fontSize, 2); DrawText(lines[i], 10, t, fontSize, RED); // Inserting extra space for real newlines, // wrapped lines are rendered closer together - t += size.y + 10; + t += (int)size.y + 10; } EndMode2D(); diff --git a/examples/shapes/shapes_clock_of_clocks.c b/examples/shapes/shapes_clock_of_clocks.c index 493e53b5e..3fc24aa92 100644 --- a/examples/shapes/shapes_clock_of_clocks.c +++ b/examples/shapes/shapes_clock_of_clocks.c @@ -14,6 +14,9 @@ * Copyright (c) 2025 JP Mortiboys (@themushroompirates) * ********************************************************************************************/ +#if defined(WIN32) +#define _CRT_SECURE_NO_WARNINGS +#endif #include "raylib.h" From 04930c5132f900be39b21a6b89685f0f75f2d0e5 Mon Sep 17 00:00:00 2001 From: Diogo Hartuiq Debarba <35925088+diogohartuiqdebarba@users.noreply.github.com> Date: Thu, 23 Oct 2025 08:27:28 -0300 Subject: [PATCH 061/102] Fix typo in RPI cross-compiler variable name (#5295) --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 0d4ca9ac7..4369d8084 100644 --- a/src/Makefile +++ b/src/Makefile @@ -283,7 +283,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW) endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) - ifeq ($(USE_RPI_CROSS_COMPILER),TRUE) + ifeq ($(USE_RPI_CROSSCOMPILER),TRUE) # Define RPI cross-compiler #CC = armv6j-hardfloat-linux-gnueabi-gcc CC = $(RPI_TOOLCHAIN)/bin/$(RPI_TOOLCHAIN_NAME)-gcc From 93c5dc3b5f67b5c221cd93f379f9b31ba15b8c94 Mon Sep 17 00:00:00 2001 From: alexgb0 Date: Thu, 23 Oct 2025 17:28:00 +0200 Subject: [PATCH 062/102] [rlsw] c++ support (#5291) * rlsw c++ support * rslw formatting fixes --- src/external/rlsw.h | 141 ++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 64 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 904bf1210..aa4803265 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -156,6 +156,12 @@ #define SW_CLIP_EPSILON 1e-4f #endif +#ifdef __cplusplus + #define CURLY_INIT(name) name +#else + #define CURLY_INIT(name) (name) +#endif + //---------------------------------------------------------------------------------- // OpenGL Compatibility Types //---------------------------------------------------------------------------------- @@ -1699,7 +1705,7 @@ static inline void sw_framebuffer_blit_to_##name( int xSrc, int ySrc, int wSrc, int hSrc, \ DST_PTR_T *dst) \ { \ - const uint8_t *srcBase = RLSW.framebuffer.color; \ + const uint8_t *srcBase = (uint8_t*)RLSW.framebuffer.color; \ int fbWidth = RLSW.framebuffer.width; \ \ uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ @@ -1722,7 +1728,7 @@ static inline void sw_framebuffer_blit_to_##name( int xSrc, int ySrc, int wSrc, int hSrc, \ DST_PTR_T *dst) \ { \ - const uint8_t *srcBase = RLSW.framebuffer.color; \ + const uint8_t *srcBase = (uint8_t *)RLSW.framebuffer.color; \ int fbWidth = RLSW.framebuffer.width; \ \ uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ @@ -2583,6 +2589,15 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, /* Scanline rasterization */ \ for (int x = xStart; x < xEnd; x++) \ { \ + /* Pixel color computation */ \ + float wRcp = 1.0f/w; \ + float srcColor[4] = { \ + color[0]*wRcp, \ + color[1]*wRcp, \ + color[2]*wRcp, \ + color[3]*wRcp \ + }; \ + \ /* Test and write depth */ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -2593,15 +2608,6 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \ sw_framebuffer_write_depth(dptr, z); \ \ - /* Pixel color computation */ \ - float wRcp = 1.0f/w; \ - float srcColor[4] = { \ - color[0]*wRcp, \ - color[1]*wRcp, \ - color[2]*wRcp, \ - color[3]*wRcp \ - }; \ - \ if (ENABLE_TEXTURE) \ { \ float texColor[4]; \ @@ -3063,6 +3069,14 @@ static inline void FUNC_NAME(void) /* Scanline rasterization */ \ for (int x = xMin; x < xMax; x++) \ { \ + /* Pixel color computation */ \ + float srcColor[4] = { \ + color[0], \ + color[1], \ + color[2], \ + color[3] \ + }; \ + \ /* Test and write depth */ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3073,14 +3087,6 @@ static inline void FUNC_NAME(void) \ sw_framebuffer_write_depth(dptr, z); \ \ - /* Pixel color computation */ \ - float srcColor[4] = { \ - color[0], \ - color[1], \ - color[2], \ - color[3] \ - }; \ - \ if (ENABLE_TEXTURE) \ { \ float texColor[4]; \ @@ -3361,6 +3367,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ { \ int offset = (y1 + i)*fbWidth + (x1 + (j >> 16)); \ void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \ + void *cptr; \ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3370,7 +3377,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ \ sw_framebuffer_write_depth(dptr, z); \ \ - void *cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ + cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ \ if (ENABLE_COLOR_BLEND) \ { \ @@ -3397,6 +3404,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ { \ int offset = (y1 + (j >> 16))*fbWidth + (x1 + i); \ void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \ + void *cptr; \ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3406,7 +3414,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ \ sw_framebuffer_write_depth(dptr, z); \ \ - void *cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ + cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ \ if (ENABLE_COLOR_BLEND) \ { \ @@ -3687,9 +3695,14 @@ static inline void sw_poly_line_render(void) const sw_vertex_t *vertices = RLSW.vertexBuffer; int cm1 = RLSW.vertexCounter - 1; - for (int i = 0; i < cm1; i++) sw_line_render((sw_vertex_t[2]){ vertices[i], vertices[i + 1] }); + for (int i = 0; i < cm1; i++) + { + sw_vertex_t verts[2] = { vertices[i], vertices[i + 1] }; + sw_line_render(verts); + } - sw_line_render((sw_vertex_t[2]){ vertices[cm1], vertices[0] }); + sw_vertex_t verts[2] = { vertices[cm1], vertices[0] }; + sw_line_render(verts); } static inline void sw_poly_fill_render(void) @@ -3817,10 +3830,10 @@ bool swInit(int w, int h) swViewport(0, 0, w, h); swScissor(0, 0, w, h); - RLSW.loadedTextures = SW_MALLOC(SW_MAX_TEXTURES*sizeof(sw_texture_t)); + RLSW.loadedTextures = (sw_texture_t *)SW_MALLOC(SW_MAX_TEXTURES*sizeof(sw_texture_t)); if (RLSW.loadedTextures == NULL) { swClose(); return false; } - RLSW.freeTextureIds = SW_MALLOC(SW_MAX_TEXTURES*sizeof(uint32_t)); + RLSW.freeTextureIds = (uint32_t *)SW_MALLOC(SW_MAX_TEXTURES*sizeof(uint32_t)); if (RLSW.loadedTextures == NULL) { swClose(); return false; } RLSW.clearColor[0] = 0.0f; @@ -3898,7 +3911,7 @@ void swClose(void) SW_FREE(RLSW.loadedTextures); SW_FREE(RLSW.freeTextureIds); - RLSW = (sw_context_t) { 0 }; + RLSW = CURLY_INIT(sw_context_t) { 0 }; } bool swResizeFramebuffer(int w, int h) @@ -3908,7 +3921,7 @@ bool swResizeFramebuffer(int w, int h) void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels) { - sw_pixelformat_t pFormat = sw_get_pixel_format(format, type); + sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type); if (w <= 0) { @@ -3930,26 +3943,26 @@ void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, switch (pFormat) { - case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_copy_to_R5G6B5(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_copy_to_R8G8B8(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_copy_to_R5G5B5A1(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_copy_to_R4G4B4A4(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_copy_to_R8G8B8A8(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_copy_to_R32(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_copy_to_R32G32B32(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_copy_to_R32G32B32A32(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_copy_to_R16(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_copy_to_R16G16B16(x, y, w, h, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_copy_to_R16G16B16A16(x, y, w, h, pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_copy_to_R5G6B5(x, y, w, h, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_copy_to_R8G8B8(x, y, w, h, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_copy_to_R5G5B5A1(x, y, w, h, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_copy_to_R4G4B4A4(x, y, w, h, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_copy_to_R8G8B8A8(x, y, w, h, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_copy_to_R32(x, y, w, h, (float *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_copy_to_R32G32B32(x, y, w, h, (float *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_copy_to_R32G32B32A32(x, y, w, h, (float *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_copy_to_R16(x, y, w, h, (sw_half_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_copy_to_R16G16B16(x, y, w, h, (sw_half_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_copy_to_R16G16B16A16(x, y, w, h, (sw_half_t *)pixels); break; default: RLSW.errCode = SW_INVALID_ENUM; break; } } void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels) { - sw_pixelformat_t pFormat = sw_get_pixel_format(format, type); + sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type); if (wSrc <= 0) { @@ -3971,19 +3984,19 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr switch (pFormat) { - case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_blit_to_R5G6B5(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_blit_to_R8G8B8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_blit_to_R5G5B5A1(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_blit_to_R4G4B4A4(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_blit_to_R8G8B8A8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_blit_to_R32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_blit_to_R32G32B32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_blit_to_R32G32B32A32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_blit_to_R16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_blit_to_R16G16B16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_blit_to_R16G16B16A16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_framebuffer_blit_to_R5G6B5(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_framebuffer_blit_to_R8G8B8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_blit_to_R5G5B5A1(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_blit_to_R4G4B4A4(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_blit_to_R8G8B8A8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_blit_to_R32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_blit_to_R32G32B32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (float *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_blit_to_R32G32B32A32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (float*)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_blit_to_R16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_blit_to_R16G16B16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_blit_to_R16G16B16A16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; default: RLSW.errCode = SW_INVALID_ENUM; break; } } @@ -4553,7 +4566,7 @@ void swBegin(SWdraw mode) void swEnd(void) { - RLSW.drawMode = 0; + RLSW.drawMode = (SWdraw)0; } void swVertex2i(int x, int y) @@ -4738,9 +4751,9 @@ void swBindArray(SWarray type, void *buffer) { switch (type) { - case SW_VERTEX_ARRAY: RLSW.array.positions = buffer; break; - case SW_TEXTURE_COORD_ARRAY: RLSW.array.texcoords = buffer; break; - case SW_COLOR_ARRAY: RLSW.array.colors = buffer; break; + case SW_VERTEX_ARRAY: RLSW.array.positions = (float *)buffer; break; + case SW_TEXTURE_COORD_ARRAY: RLSW.array.texcoords = (float *)buffer; break; + case SW_COLOR_ARRAY: RLSW.array.colors = (uint8_t *)buffer; break; default: break; } } @@ -4833,7 +4846,7 @@ void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy if (copy) { - int bytes = sw_get_pixel_bytes(pixelFormat); + int bytes = sw_get_pixel_bytes((sw_pixelformat_t)pixelFormat); int size = bytes*width*height; texture->pixels.ptr = SW_MALLOC(size); @@ -4854,7 +4867,7 @@ void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy texture->height = height; texture->wMinus1 = width - 1; texture->hMinus1 = height - 1; - texture->format = pixelFormat; + texture->format = (sw_pixelformat_t)pixelFormat; texture->tx = 1.0f/width; texture->ty = 1.0f/height; texture->copy = copy; @@ -4882,7 +4895,7 @@ void swTexParameteri(int param, int value) return; } - texture->minFilter = value; + texture->minFilter = (SWfilter)value; } break; case SW_TEXTURE_MAG_FILTER: { @@ -4892,7 +4905,7 @@ void swTexParameteri(int param, int value) return; } - texture->magFilter = value; + texture->magFilter = (SWfilter)value; } break; case SW_TEXTURE_WRAP_S: { @@ -4902,7 +4915,7 @@ void swTexParameteri(int param, int value) return; } - texture->sWrap = value; + texture->sWrap = (SWwrap)value; } break; case SW_TEXTURE_WRAP_T: { @@ -4912,7 +4925,7 @@ void swTexParameteri(int param, int value) return; } - texture->tWrap = value; + texture->tWrap = (SWwrap)value; } break; default: RLSW.errCode = SW_INVALID_ENUM; break; } From 12dc0d66758970212eaa323c2e398d8645a229e4 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Thu, 23 Oct 2025 08:45:33 -0700 Subject: [PATCH 063/102] Revert undesired change to rcore and restore correct win32 ifdef and max path (#5297) Fixes #5293 also add comment for win32 platform. --- src/rcore.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/rcore.c b/src/rcore.c index 350490ad1..e4628e77c 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -26,7 +26,8 @@ * - Linux DRM subsystem (KMS mode) * > PLATFORM_ANDROID: * - Android (ARM, ARM64) -* +* > PLATFORM_DESKTOP_WIN32 (Native Win32): +* - Windows (Win32, Win64) * CONFIGURATION: * #define SUPPORT_DEFAULT_FONT (default) * Default font is loaded on window initialization to be available for the user to render simple text. @@ -161,7 +162,10 @@ #endif // Platform specific defines to handle GetApplicationDirectory() -#if (defined(_WIN32) && !defined(PLATFORM_DESKTOP_RGFW)) || (defined(_MSC_VER) && defined(PLATFORM_DESKTOP_RGFW)) +#if defined(_WIN32) + #if !defined(MAX_PATH) + #define MAX_PATH 260 + #endif struct HINSTANCE__; #if defined(__cplusplus) From 39242dba2303cd321e594908c814e08f976d31b4 Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Fri, 24 Oct 2025 18:29:01 +0200 Subject: [PATCH 064/102] [rlsw] Smarter texture management (#5296) * simplified framebuffer management * convert texture to rgba32 * remove float copy/blit * adding SIMD framebuffer read/write This adds SIMD framebuffer read/write, and also texel fetch. This supports SSE2/SSE41 and SISD fallback (also includes ARM NEON support, conceptually identical but still needs testing). * consistency * tweaks * review of `sw_texture_sample_linear` * better quad sorting unrelated to the PR, but at least it's done * ignore some pipeline state in certains context * convention tweaks --------- Co-authored-by: Ray --- src/external/rlsw.h | 1721 ++++++++++++++++++------------------------- 1 file changed, 723 insertions(+), 998 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index aa4803265..626cb2cc5 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -115,16 +115,12 @@ #define SW_GL_FRAMEBUFFER_COPY_BGRA true #endif -#ifndef SW_GL_BINDING_COPY_TEXTURE - #define SW_GL_BINDING_COPY_TEXTURE true -#endif - #ifndef SW_COLOR_BUFFER_BITS - #define SW_COLOR_BUFFER_BITS 24 + #define SW_COLOR_BUFFER_BITS 32 //< 32 (rgba), 16 (rgb packed) or 8 (rgb packed) #endif #ifndef SW_DEPTH_BUFFER_BITS - #define SW_DEPTH_BUFFER_BITS 16 + #define SW_DEPTH_BUFFER_BITS 16 //< 24, 16 or 8 #endif #ifndef SW_MAX_PROJECTION_STACK_SIZE @@ -382,7 +378,7 @@ typedef double GLclampd; #define glDrawArrays(m, o, c) swDrawArrays((m), (o), (c)) #define glGenTextures(c, v) swGenTextures((c), (v)) #define glDeleteTextures(c, v) swDeleteTextures((c), (v)) -#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), SW_GL_BINDING_COPY_TEXTURE, (p)) +#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p)) #define glTexParameteri(tr, pname, param) swTexParameteri((pname), (param)) #define glBindTexture(tr, id) swBindTexture((id)) @@ -597,7 +593,7 @@ SWAPI void swDrawArrays(SWdraw mode, int offset, int count); SWAPI void swGenTextures(int count, uint32_t *textures); SWAPI void swDeleteTextures(int count, uint32_t *textures); -SWAPI void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy, const void *data); +SWAPI void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data); SWAPI void swTexParameteri(int param, int value); SWAPI void swBindTexture(uint32_t id); @@ -615,6 +611,65 @@ SWAPI void swBindTexture(uint32_t id); #include #include // Required for: floorf(), fabsf() +#if defined(__FMA__) && defined(__AVX2__) +# define SW_HAS_FMA_AVX2 +# include +#endif + +#if defined(__FMA__) && defined(__AVX__) +# define SW_HAS_FMA_AVX +# include +#endif + +#if defined(__AVX2__) +# define SW_HAS_AVX2 +# include +#endif + +#if defined(__AVX__) +# define SW_HAS_AVX +# include +#endif + +#if defined(__SSE4_2__) +# define SW_HAS_SSE42 +# include +#endif + +#if defined(__SSE4_1__) +# define SW_HAS_SSE41 +# include +#endif + +#if defined(__SSSE3__) +# define SW_HAS_SSSE3 +# include +#endif + +#if defined(__SSE3__) +# define SW_HAS_SSE3 +# include +#endif + +#if defined(__SSE2__) +# define SW_HAS_SSE2 +# include +#endif + +#if defined(__SSE__) +# define SW_HAS_SSE +# include +#endif + +#if defined(__ARM_NEON) || defined(__aarch64__) +# if defined(__ARM_FEATURE_FMA) +# define SW_HAS_NEON_FMA +# else +# define SW_HAS_NEON +# endif +# include +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -625,7 +680,69 @@ SWAPI void swBindTexture(uint32_t id); #define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS/8) #define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS/8) -#define SW_STATE_CHECK(flags) ((RLSW.stateFlags & (flags)) == (flags)) +#if (SW_COLOR_BUFFER_BITS == 8) + #define COLOR_TYPE uint8_t + #define COLOR_IS_PACKED 1 + #define PACK_COLOR(r,g,b) ((((uint8_t)((r)*7+0.5f))&0x07)<<5 | (((uint8_t)((g)*7+0.5f))&0x07)<<2 | ((uint8_t)((b)*3+0.5f))&0x03) + #define UNPACK_R(p) (((p)>>5)&0x07) + #define UNPACK_G(p) (((p)>>2)&0x07) + #define UNPACK_B(p) ((p)&0x03) + #define SCALE_R(v) ((v)*255+3)/7 + #define SCALE_G(v) ((v)*255+3)/7 + #define SCALE_B(v) ((v)*255+1)/3 + #define TO_FLOAT_R(v) ((v)*(1.0f/7.0f)) + #define TO_FLOAT_G(v) ((v)*(1.0f/7.0f)) + #define TO_FLOAT_B(v) ((v)*(1.0f/3.0f)) +#elif (SW_COLOR_BUFFER_BITS == 16) + #define COLOR_TYPE uint16_t + #define COLOR_IS_PACKED 1 + #define PACK_COLOR(r,g,b) ((((uint16_t)((r)*31+0.5f))&0x1F)<<11 | (((uint16_t)((g)*63+0.5f))&0x3F)<<5 | ((uint16_t)((b)*31+0.5f))&0x1F) + #define UNPACK_R(p) (((p)>>11)&0x1F) + #define UNPACK_G(p) (((p)>>5)&0x3F) + #define UNPACK_B(p) ((p)&0x1F) + #define SCALE_R(v) ((v)*255+15)/31 + #define SCALE_G(v) ((v)*255+31)/63 + #define SCALE_B(v) ((v)*255+15)/31 + #define TO_FLOAT_R(v) ((v)*(1.0f/31.0f)) + #define TO_FLOAT_G(v) ((v)*(1.0f/63.0f)) + #define TO_FLOAT_B(v) ((v)*(1.0f/31.0f)) +#else // 32 bits + #define COLOR_TYPE uint8_t + #define COLOR_IS_PACKED 0 +#endif + +#if (SW_DEPTH_BUFFER_BITS == 8) + #define DEPTH_TYPE uint8_t + #define DEPTH_IS_PACKED 1 + #define DEPTH_MAX UINT8_MAX + #define DEPTH_SCALE (1.0f/UINT8_MAX) + #define PACK_DEPTH(d) ((DEPTH_TYPE)((d)*DEPTH_MAX)) + #define UNPACK_DEPTH(p) (p) +#elif (SW_DEPTH_BUFFER_BITS == 16) + #define DEPTH_TYPE uint16_t + #define DEPTH_IS_PACKED 1 + #define DEPTH_MAX UINT16_MAX + #define DEPTH_SCALE (1.0f/UINT16_MAX) + #define PACK_DEPTH(d) ((DEPTH_TYPE)((d)*DEPTH_MAX)) + #define UNPACK_DEPTH(p) (p) +#else // 24 bits + #define DEPTH_TYPE uint8_t + #define DEPTH_IS_PACKED 0 + #define DEPTH_MAX 0xFFFFFF + #define DEPTH_SCALE (1.0f/0xFFFFFF) + #define PACK_DEPTH_0(d) (((uint32_t)((d)*DEPTH_MAX)>>16)&0xFF) + #define PACK_DEPTH_1(d) (((uint32_t)((d)*DEPTH_MAX)>>8)&0xFF) + #define PACK_DEPTH_2(d) ((uint32_t)((d)*DEPTH_MAX)&0xFF) + #define UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) +#endif + +#define GET_COLOR_PTR(ptr, offset) ((void*)((uint8_t*)(ptr) + (offset)*SW_COLOR_PIXEL_SIZE)) +#define GET_DEPTH_PTR(ptr, offset) ((void*)((uint8_t*)(ptr) + (offset)*SW_DEPTH_PIXEL_SIZE)) +#define INC_COLOR_PTR(ptr) ((ptr) = (void*)((uint8_t*)(ptr) + SW_COLOR_PIXEL_SIZE)) +#define INC_DEPTH_PTR(ptr) ((ptr) = (void*)((uint8_t*)(ptr) + SW_DEPTH_PIXEL_SIZE)) + +#define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) +#define SW_STATE_CHECK_EX(state, flags) (((state) & (flags)) == (flags)) #define SW_STATE_SCISSOR_TEST (1 << 0) #define SW_STATE_TEXTURE_2D (1 << 1) @@ -674,16 +791,11 @@ typedef struct { } sw_vertex_t; typedef struct { - // Dirty hack for copied data - // TODO: Rework copied image handling - union { - const void *cptr; // NOTE: Is used for all data reads - void *ptr; // WARNING: Should only be used to allocate and free data - } pixels; + + uint8_t* pixels; // Texture pixels (RGBA32) int width, height; // Dimensions of the texture int wMinus1, hMinus1; // Dimensions minus one - sw_pixelformat_t format; // Pixel format (internal representation) SWfilter minFilter; // Minification filter SWfilter magFilter; // Magnification filter @@ -694,8 +806,6 @@ typedef struct { float tx; // Texel width float ty; // Texel height - bool copy; // Flag indicating whether memory has been allocated - } sw_texture_t; typedef struct { @@ -943,8 +1053,89 @@ static inline void sw_add_vertex_grad_PTCH( out->homogeneous[3] += gradients->homogeneous[3]; } -// Half floating point management functions -static inline uint32_t sw_f16_to_f32_ui(uint16_t h) +static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) +{ +#if defined(SW_HAS_NEON) + float32x4_t values = vld1q_f32(src); + float32x4_t scaled = vmulq_n_f32(values, 255.0f); + scaled = vminq_f32(vmaxq_f32(scaled, vdupq_n_f32(0.0f)), vdupq_n_f32(255.0f)); + uint32x4_t clamped = vcvtq_u32_f32(scaled); + + uint16x4_t narrow16 = vmovn_u32(clamped); + uint8x8_t narrow8 = vmovn_u16(vcombine_u16(narrow16, narrow16)); + + vst1_lane_u32((uint32_t*)dst, vreinterpret_u32_u8(narrow8), 0); + +#elif defined(SW_HAS_SSE41) + __m128 values = _mm_loadu_ps(src); + __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); + scaled = _mm_max_ps(_mm_min_ps(scaled, _mm_set1_ps(255.0f)), _mm_setzero_ps()); + __m128i clamped = _mm_cvtps_epi32(scaled); + + clamped = _mm_packus_epi32(clamped, clamped); + clamped = _mm_packus_epi16(clamped, clamped); + *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); + +#elif defined(SW_HAS_SSE2) + __m128 values = _mm_loadu_ps(src); + __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); + scaled = _mm_max_ps(_mm_min_ps(scaled, _mm_set1_ps(255.0f)), _mm_setzero_ps()); + __m128i clamped = _mm_cvtps_epi32(scaled); + + clamped = _mm_packs_epi32(clamped, clamped); + clamped = _mm_packus_epi16(clamped, clamped); + *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); + +#else + for (int i = 0; i < 4; i++) + { + float val = src[i]*255.0f; + val = (val > 255.0f)? 255.0f : val; + val = (val < 0.0f)? 0.0f : val; + dst[i] = (uint8_t)(val + 0.5f); + } +#endif +} + +static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) +{ +#if defined(SW_HAS_NEON) + uint32x4_t bytes = vdupq_n_u32(0); + bytes = vld1q_lane_u32((const uint32_t*)src, bytes, 0); + + uint8x8_t bytes8 = vreinterpret_u8_u32(vget_low_u32(bytes)); + uint16x8_t bytes16 = vmovl_u8(bytes8); + uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16)); + + float32x4_t floats = vcvtq_f32_u32(ints); + floats = vmulq_n_f32(floats, 1.0f/255.0f); + vst1q_f32(dst, floats); + +#elif defined(SW_HAS_SSE41) + __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); + __m128i ints = _mm_cvtepu8_epi32(bytes); + __m128 floats = _mm_cvtepi32_ps(ints); + floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); + _mm_storeu_ps(dst, floats); + +#elif defined(SW_HAS_SSE2) + __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); + bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128()); + __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128()); + __m128 floats = _mm_cvtepi32_ps(ints); + floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); + _mm_storeu_ps(dst, floats); + +#else + dst[0] = (float)src[0]/255.0f; + dst[1] = (float)src[1]/255.0f; + dst[2] = (float)src[2]/255.0f; + dst[3] = (float)src[3]/255.0f; +#endif +} + +// Half conversion functions +static inline uint32_t sw_half_to_float_ui(uint16_t h) { uint32_t s = (uint32_t)(h & 0x8000) << 16; int32_t em = h & 0x7fff; @@ -962,14 +1153,14 @@ static inline uint32_t sw_f16_to_f32_ui(uint16_t h) return s | r; } -static inline float sw_f16_to_f32(sw_half_t y) +static inline float sw_half_to_float(sw_half_t y) { - union { float f; uint32_t i; } v = { .i = sw_f16_to_f32_ui(y) }; + union { float f; uint32_t i; } v = { .i = sw_half_to_float_ui(y) }; return v.f; } -static inline uint16_t sw_f16_from_f32_ui(uint32_t ui) +static inline uint16_t sw_half_from_float_ui(uint32_t ui) { int32_t s = (ui >> 16) & 0x8000; int32_t em = ui & 0x7fffffff; @@ -989,14 +1180,15 @@ static inline uint16_t sw_f16_from_f32_ui(uint32_t ui) return (uint16_t)(s | h); } -static inline sw_half_t sw_f16_from_f32(float i) +static inline sw_half_t sw_half_from_float(float i) { union { float f; uint32_t i; } v; v.f = i; - return sw_f16_from_f32_ui(v.i); + return sw_half_from_float_ui(v.i); } // Framebuffer management functions + static inline bool sw_framebuffer_load(int w, int h) { int size = w*h; @@ -1005,7 +1197,11 @@ static inline bool sw_framebuffer_load(int w, int h) if (RLSW.framebuffer.color == NULL) return false; RLSW.framebuffer.depth = SW_MALLOC(SW_DEPTH_PIXEL_SIZE*size); - if (RLSW.framebuffer.depth == NULL) return false; + if (RLSW.framebuffer.depth == NULL) + { + SW_FREE(RLSW.framebuffer.color); + return false; + } RLSW.framebuffer.width = w; RLSW.framebuffer.height = h; @@ -1025,11 +1221,15 @@ static inline bool sw_framebuffer_resize(int w, int h) return true; } - void *newColor = SW_REALLOC(RLSW.framebuffer.color, newSize); + void *newColor = SW_REALLOC(RLSW.framebuffer.color, SW_COLOR_PIXEL_SIZE*newSize); if (newColor == NULL) return false; - void *newDepth = SW_REALLOC(RLSW.framebuffer.depth, newSize); - if (newDepth == NULL) return false; + void *newDepth = SW_REALLOC(RLSW.framebuffer.depth, SW_DEPTH_PIXEL_SIZE*newSize); + if (newDepth == NULL) + { + SW_FREE(newColor); + return false; + } RLSW.framebuffer.color = newColor; RLSW.framebuffer.depth = newDepth; @@ -1041,314 +1241,221 @@ static inline bool sw_framebuffer_resize(int w, int h) return true; } -static inline void *sw_framebuffer_get_color_addr(const void *ptr, uint32_t offset) -{ - return (uint8_t *)ptr + offset*SW_COLOR_PIXEL_SIZE; -} - -static inline void sw_framebuffer_inc_color_addr(void **ptr) -{ - *ptr = (void *)(((uint8_t *)*ptr) + SW_COLOR_PIXEL_SIZE); -} - -static inline void sw_framebuffer_inc_const_color_addr(const void **ptr) -{ - *ptr = (const void *)(((const uint8_t *)*ptr) + SW_COLOR_PIXEL_SIZE); -} - -static inline void *sw_framebuffer_get_depth_addr(const void *ptr, uint32_t offset) -{ - return (uint8_t *)ptr + offset*SW_DEPTH_PIXEL_SIZE; -} - -static inline void sw_framebuffer_inc_depth_addr(void* *ptr) -{ - *ptr = (void*)(((uint8_t *)*ptr) + SW_DEPTH_PIXEL_SIZE); -} - -#if (SW_COLOR_BUFFER_BITS == 8) // RGB - (3:3:2) static inline void sw_framebuffer_read_color(float dst[4], const void *src) { - uint8_t pixel = ((uint8_t *)src)[0]; - - dst[0] = ((pixel >> 5) & 0x07)*(1.0f/7.0f); - dst[1] = ((pixel >> 2) & 0x07)*(1.0f/7.0f); - dst[2] = (pixel & 0x03)*(1.0f/3.0f); +#if COLOR_IS_PACKED + COLOR_TYPE pixel = ((COLOR_TYPE*)src)[0]; + dst[0] = TO_FLOAT_R(UNPACK_R(pixel)); + dst[1] = TO_FLOAT_G(UNPACK_G(pixel)); + dst[2] = TO_FLOAT_B(UNPACK_B(pixel)); dst[3] = 1.0f; +#else + sw_float_from_unorm8_simd(dst, src); +#endif } static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src) { - uint8_t pixel = ((const uint8_t *)src)[0]; - - uint8_t r = (pixel >> 5) & 0x07; - uint8_t g = (pixel >> 2) & 0x07; - uint8_t b = pixel & 0x03; - - dst[0] = (r*255 + 3)/7; - dst[1] = (g*255 + 3)/7; - dst[2] = (b*255 + 1)/3; +#if COLOR_IS_PACKED + COLOR_TYPE pixel = ((COLOR_TYPE*)src)[0]; + dst[0] = SCALE_R(UNPACK_R(pixel)); + dst[1] = SCALE_G(UNPACK_G(pixel)); + dst[2] = SCALE_B(UNPACK_B(pixel)); dst[3] = 255; +#else + const COLOR_TYPE *p = (const COLOR_TYPE*)src; + dst[0] = p[0]; + dst[1] = p[1]; + dst[2] = p[2]; + dst[3] = p[3]; +#endif } -static inline void sw_framebuffer_write_color(void *dst, const float color[3]) +static inline void sw_framebuffer_write_color(void *dst, const float src[4]) { - uint8_t r = ((uint8_t)(color[0]*UINT8_MAX) >> 5) & 0x07; - uint8_t g = ((uint8_t)(color[1]*UINT8_MAX) >> 5) & 0x07; - uint8_t b = ((uint8_t)(color[2]*UINT8_MAX) >> 6) & 0x03; - - ((uint8_t *)dst)[0] = (r << 5) | (g << 2) | b; +#if COLOR_IS_PACKED + ((COLOR_TYPE*)dst)[0] = PACK_COLOR(src[0], src[1], src[2]); +#else + sw_float_to_unorm8_simd(dst, src); +#endif } -static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3]) +static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[4]) { - uint8_t r8 = (uint8_t)(color[0]*7.0f + 0.5f); - uint8_t g8 = (uint8_t)(color[1]*7.0f + 0.5f); - uint8_t b8 = (uint8_t)(color[2]*3.0f + 0.5f); - - uint8_t packedColor = ((r8 & 0x07) << 5) | ((g8 & 0x07) << 2) | (b8 & 0x03); - - uint8_t *p = (uint8_t *)ptr; - +#if COLOR_IS_PACKED + COLOR_TYPE packed = PACK_COLOR(color[0], color[1], color[2]); + COLOR_TYPE *p = (COLOR_TYPE*)ptr; +#else + COLOR_TYPE r = sw_clampi(color[0]*255, 0, 255); + COLOR_TYPE g = sw_clampi(color[1]*255, 0, 255); + COLOR_TYPE b = sw_clampi(color[2]*255, 0, 255); + COLOR_TYPE a = sw_clampi(color[3]*255, 0, 255); + COLOR_TYPE *p = (COLOR_TYPE*)ptr; +#endif + if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; + int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) { - uint8_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = packedColor; - } - } - else - { - for (int i = 0; i < size; i++) *p++ = packedColor; - } -} - -#elif (SW_COLOR_BUFFER_BITS == 16) // RGB - (5:6:5) - -static inline void sw_framebuffer_read_color(float dst[4], const void *src) -{ - uint16_t pixel = ((uint16_t *)src)[0]; - - dst[0] = ((pixel >> 11) & 0x1F)*(1.0f/31.0f); - dst[1] = ((pixel >> 5) & 0x3F)*(1.0f/63.0f); - dst[2] = (pixel & 0x1F)*(1.0f/31.0f); - dst[3] = 1.0f; -} - -static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src) -{ - uint16_t pixel = ((const uint16_t *)src)[0]; - - uint8_t r = (pixel >> 11) & 0x1F; - uint8_t g = (pixel >> 5) & 0x3F; - uint8_t b = pixel & 0x1F; - - dst[0] = (r*255 + 15)/31; - dst[1] = (g*255 + 31)/63; - dst[2] = (b*255 + 15)/31; - dst[3] = 255; -} - -static inline void sw_framebuffer_write_color(void *dst, const float color[3]) -{ - uint8_t r = (uint8_t)(color[0]*31.0f + 0.5f) & 0x1F; - uint8_t g = (uint8_t)(color[1]*63.0f + 0.5f) & 0x3F; - uint8_t b = (uint8_t)(color[2]*31.0f + 0.5f) & 0x1F; - - ((uint16_t *)dst)[0] = (r << 11) | (g << 5) | b; -} - -static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3]) -{ - uint16_t r16 = (uint16_t)(color[0]*31.0f + 0.5f); - uint16_t g_16 = (uint16_t)(color[1]*63.0f + 0.5f); - uint16_t b_16 = (uint16_t)(color[2]*31.0f + 0.5f); - - uint16_t packedColor = ((r16 & 0x1F) << 11) | ((g_16 & 0x3F) << 5) | (b_16 & 0x1F); - - uint16_t *p = (uint16_t *)ptr; - - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) - { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; - for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) - { - uint16_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = packedColor; - } - } - else - { - for (int i = 0; i < size; i++) *p++ = packedColor; - } -} - -#elif (SW_COLOR_BUFFER_BITS == 24) // RGB - (8:8:8) - -static inline void sw_framebuffer_read_color(float dst[4], const void *src) -{ - dst[0] = ((uint8_t *)src)[0]*(1.0f/255.0f); - dst[1] = ((uint8_t *)src)[1]*(1.0f/255.0f); - dst[2] = ((uint8_t *)src)[2]*(1.0f/255.0f); - dst[3] = 1.0f; -} - -static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src) -{ - dst[0] = ((uint8_t *)src)[0]; - dst[1] = ((uint8_t *)src)[1]; - dst[2] = ((uint8_t *)src)[2]; - dst[3] = 255; -} - -static inline void sw_framebuffer_write_color(void *dst, const float color[3]) -{ - ((uint8_t *)dst)[0] = (uint8_t)(color[0]*UINT8_MAX); - ((uint8_t *)dst)[1] = (uint8_t)(color[1]*UINT8_MAX); - ((uint8_t *)dst)[2] = (uint8_t)(color[2]*UINT8_MAX); -} - -static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[3]) -{ - uint8_t r = (uint8_t)(color[0]*255.0f); - uint8_t g = (uint8_t)(color[1]*255.0f); - uint8_t b = (uint8_t)(color[2]*255.0f); - - uint8_t *p = (uint8_t *)ptr; - - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) - { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; - for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) - { - uint8_t *curPtr = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); - for (int xCount = 0; xCount < wScissor; xCount++) +#if COLOR_IS_PACKED + COLOR_TYPE *row = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; + for (int x = 0; x < w; x++) *row++ = packed; +#else + COLOR_TYPE *row = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); + for (int x = 0; x < w; x++) { - *curPtr++ = r; - *curPtr++ = g; - *curPtr++ = b; + *row++ = r; + *row++ = g; + *row++ = b; + *row++ = a; } +#endif } } else { +#if COLOR_IS_PACKED + for (int i = 0; i < size; i++) *p++ = packed; +#else for (int i = 0; i < size; i++) { *p++ = r; *p++ = g; *p++ = b; + *p++ = a; } +#endif } } -#endif // SW_COLOR_BUFFER_BITS - -#if (SW_DEPTH_BUFFER_BITS == 8) - static inline float sw_framebuffer_read_depth(const void *src) { - return (float)((uint8_t *)src)[0]*(1.0f/UINT8_MAX); +#if DEPTH_IS_PACKED + return ((DEPTH_TYPE*)src)[0]*DEPTH_SCALE; +#else + const DEPTH_TYPE *p = (const DEPTH_TYPE*)src; + uint32_t d = UNPACK_DEPTH(p); + return d*DEPTH_SCALE; +#endif } static inline void sw_framebuffer_write_depth(void *dst, float depth) { - ((uint8_t *)dst)[0] = (uint8_t)(depth*UINT8_MAX); +#if DEPTH_IS_PACKED + ((DEPTH_TYPE*)dst)[0] = PACK_DEPTH(depth); +#else + DEPTH_TYPE *p = (DEPTH_TYPE*)dst; + p[0] = PACK_DEPTH_0(depth); + p[1] = PACK_DEPTH_1(depth); + p[2] = PACK_DEPTH_2(depth); +#endif } static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value) { - uint8_t d8 = (uint8_t)(value*UINT8_MAX); - uint8_t *p = (uint8_t *)ptr; - +#if DEPTH_IS_PACKED + DEPTH_TYPE d = PACK_DEPTH(value); + DEPTH_TYPE *p = (DEPTH_TYPE*)ptr; +#else + DEPTH_TYPE d0 = PACK_DEPTH_0(value); + DEPTH_TYPE d1 = PACK_DEPTH_1(value); + DEPTH_TYPE d2 = PACK_DEPTH_2(value); + DEPTH_TYPE *p = (DEPTH_TYPE*)ptr; +#endif + if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; + int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) { - uint8_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = d8; - } - } - else - { - for (int i = 0; i < size; i++) *p++ = d8; - } -} - -#elif (SW_DEPTH_BUFFER_BITS == 16) - -static inline float sw_framebuffer_read_depth(const void *src) -{ - return (float)((uint16_t *)src)[0]*(1.0f/UINT16_MAX); -} - -static inline void sw_framebuffer_write_depth(void *dst, float depth) -{ - ((uint16_t *)dst)[0] = (uint16_t)(depth*UINT16_MAX); -} - -static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value) -{ - uint16_t d16 = (uint16_t)(value*UINT16_MAX); - uint16_t *p = (uint16_t *)ptr; - - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) - { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; - for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) - { - uint16_t *curPtr = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int xCount = 0; xCount < wScissor; xCount++) *curPtr++ = d16; - } - } - else - { - for (int i = 0; i < size; i++) *p++ = d16; - } -} - -#elif (SW_DEPTH_BUFFER_BITS == 24) - -static inline float sw_framebuffer_read_depth(const void *src) -{ - uint32_t depth24 = (((uint8_t *)src)[0] << 16) | - (((uint8_t *)src)[1] << 8) | - ((uint8_t *)src)[2]; - - return depth24/(float)0xFFFFFF; -} - -static inline void sw_framebuffer_write_depth(void *dst, float depth) -{ - uint32_t depth24 = (uint32_t)(depth*0xFFFFFF); - - ((uint8_t *)dst)[0] = (depth24 >> 16) & 0xFF; - ((uint8_t *)dst)[1] = (depth24 >> 8) & 0xFF; - ((uint8_t *)dst)[2] = depth24 & 0xFF; -} - -static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value) -{ - uint32_t d32 = (uint32_t)(value*UINT32_MAX); - uint8_t d_byte0 = (uint8_t)((d32 >> 16) & 0xFF); - uint8_t d_byte1 = (uint8_t)((d32 >> 8) & 0xFF); - uint8_t d_byte2 = (uint8_t)(d32 & 0xFF); - - uint8_t *p = (uint8_t *)ptr; - - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) - { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; - for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) - { - uint8_t *curPtr = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); - for (int xCount = 0; xCount < wScissor; xCount++) +#if DEPTH_IS_PACKED + DEPTH_TYPE *row = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; + for (int x = 0; x < w; x++) *row++ = d; +#else + DEPTH_TYPE *row = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); + for (int x = 0; x < w; x++) { - *curPtr++ = d_byte0; - *curPtr++ = d_byte1; - *curPtr++ = d_byte2; + *row++ = d0; + *row++ = d1; + *row++ = d2; + } +#endif + } + } + else + { +#if DEPTH_IS_PACKED + for (int i = 0; i < size; i++) *p++ = d; +#else + for (int i = 0; i < size; i++) + { + *p++ = d0; + *p++ = d1; + *p++ = d2; + } +#endif + } +} + +static inline void sw_framebuffer_fill(void *colorPtr, void *depthPtr, int size, float color[4], float depth) +{ +#if COLOR_IS_PACKED + COLOR_TYPE packedColor = PACK_COLOR(color[0], color[1], color[2]); + COLOR_TYPE *pColor = (COLOR_TYPE*)colorPtr; +#else + COLOR_TYPE r = sw_clampi(color[0]*255, 0, 255); + COLOR_TYPE g = sw_clampi(color[1]*255, 0, 255); + COLOR_TYPE b = sw_clampi(color[2]*255, 0, 255); + COLOR_TYPE a = sw_clampi(color[3]*255, 0, 255); + COLOR_TYPE *pColor = (COLOR_TYPE*)colorPtr; +#endif + +#if DEPTH_IS_PACKED + DEPTH_TYPE d = PACK_DEPTH(depth); + DEPTH_TYPE *pDepth = (DEPTH_TYPE*)depthPtr; +#else + DEPTH_TYPE d0 = PACK_DEPTH_0(depth); + DEPTH_TYPE d1 = PACK_DEPTH_1(depth); + DEPTH_TYPE d2 = PACK_DEPTH_2(depth); + DEPTH_TYPE *pDepth = (DEPTH_TYPE*)depthPtr; +#endif + + if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) + { + int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; + for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) + { +#if COLOR_IS_PACKED + COLOR_TYPE *rowColor = pColor + y*RLSW.framebuffer.width + RLSW.scMin[0]; +#else + COLOR_TYPE *rowColor = pColor + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); +#endif + +#if DEPTH_IS_PACKED + DEPTH_TYPE *rowDepth = pDepth + y*RLSW.framebuffer.width + RLSW.scMin[0]; +#else + DEPTH_TYPE *rowDepth = pDepth + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); +#endif + + for (int x = 0; x < w; x++) + { +#if COLOR_IS_PACKED + *rowColor++ = packedColor; +#else + *rowColor++ = r; + *rowColor++ = g; + *rowColor++ = b; + *rowColor++ = a; +#endif + +#if DEPTH_IS_PACKED + *rowDepth++ = d; +#else + *rowDepth++ = d0; + *rowDepth++ = d1; + *rowDepth++ = d2; +#endif } } } @@ -1356,140 +1463,27 @@ static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value) { for (int i = 0; i < size; i++) { - *p++ = d_byte0; - *p++ = d_byte1; - *p++ = d_byte2; +#if COLOR_IS_PACKED + *pColor++ = packedColor; +#else + *pColor++ = r; + *pColor++ = g; + *pColor++ = b; + *pColor++ = a; +#endif + +#if DEPTH_IS_PACKED + *pDepth++ = d; +#else + *pDepth++ = d0; + *pDepth++ = d1; + *pDepth++ = d2; +#endif } } } -#endif // SW_DEPTH_BUFFER_BITS - -static inline void sw_framebuffer_fill(void *colorPtr, void *depthPtr, int size, float color[4], float depth_value) -{ -#if (SW_COLOR_BUFFER_BITS == 8) - // Calculate and pack 3:3:2 color - // Scale color components to the max value for each bit depth and round - uint8_t r8 = (uint8_t)(color[0]*7.0f + 0.5f); - uint8_t g8 = (uint8_t)(color[1]*7.0f + 0.5f); - uint8_t b8 = (uint8_t)(color[2]*3.0f + 0.5f); - // Pack the components into a single byte - uint8_t packedColor = ((r8 & 0x07) << 5) | ((g8 & 0x07) << 2) | (b8 & 0x03); - uint8_t *cptr = (uint8_t *)colorPtr; -#elif (SW_COLOR_BUFFER_BITS == 16) - // Calculate and pack 5:6:5 color - // Scale color components to the max value for each bit depth and round - uint16_t r16 = (uint16_t)(color[0]*31.0f + 0.5f); - uint16_t g16 = (uint16_t)(color[1]*63.0f + 0.5f); - uint16_t b16 = (uint16_t)(color[2]*31.0f + 0.5f); - // Pack the components into a 16-bit value - uint16_t packedColor = ((r16 & 0x1F) << 11) | ((g16 & 0x3F) << 5) | (b16 & 0x1F); - uint16_t *cptr = (uint16_t *)colorPtr; -#elif (SW_COLOR_BUFFER_BITS == 24) - // Calculate 8:8:8 color components - uint8_t r24 = (uint8_t)(color[0]*255.0f); - uint8_t g24 = (uint8_t)(color[1]*255.0f); - uint8_t b24 = (uint8_t)(color[2]*255.0f); - uint8_t *cptr = (uint8_t *)colorPtr; -#endif - -#if (SW_DEPTH_BUFFER_BITS == 8) - // Calculate 8-bit depth - uint8_t d8 = (uint8_t)(depth_value*UINT8_MAX); - uint8_t *dptr = (uint8_t *)depthPtr; -#elif (SW_DEPTH_BUFFER_BITS == 16) - // Calculate 16-bit depth - uint16_t d16 = (uint16_t)(depth_value*UINT16_MAX); - uint16_t *dptr = (uint16_t *)depthPtr; -#elif (SW_DEPTH_BUFFER_BITS == 24) - // Calculate 24-bit depth and pre-calculate bytes - uint32_t d32 = (uint32_t)(depth_value*UINT32_MAX); - uint8_t dByte0 = (uint8_t)((d32 >> 16) & 0xFF); - uint8_t dByte1 = (uint8_t)((d32 >> 8) & 0xFF); - uint8_t dByte2 = (uint8_t)(d32 & 0xFF); - uint8_t *dptr = (uint8_t *)depthPtr; -#endif - - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) - { - int wScissor = RLSW.scMax[0] - RLSW.scMin[0] + 1; - for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) - { - int rowStartIdx = y*RLSW.framebuffer.width + RLSW.scMin[0]; - - // Calculate starting pointers for the current row within the scissor rectangle - #if (SW_COLOR_BUFFER_BITS == 8) - uint8_t *curCPtr = cptr + rowStartIdx; - #elif (SW_COLOR_BUFFER_BITS == 16) - uint16_t *curCPtr = cptr + rowStartIdx; - #elif (SW_COLOR_BUFFER_BITS == 24) - uint8_t *curCPtr = cptr + 3*rowStartIdx; - #endif - - #if (SW_DEPTH_BUFFER_BITS == 8) - uint8_t *curDPtr = dptr + rowStartIdx; - #elif (SW_DEPTH_BUFFER_BITS == 16) - uint16_t *curDPtr = dptr + rowStartIdx; - #elif (SW_DEPTH_BUFFER_BITS == 24) - uint8_t *curDPtr = dptr + 3*rowStartIdx; - #endif - - // Fill the current row within the scissor rectangle - for (int xCount = 0; xCount < wScissor; xCount++) - { - // Write color - #if (SW_COLOR_BUFFER_BITS == 8) - *curCPtr++ = packedColor; - #elif (SW_COLOR_BUFFER_BITS == 16) - *curCPtr++ = packedColor; - #elif (SW_COLOR_BUFFER_BITS == 24) - *curCPtr++ = r24; - *curCPtr++ = g24; - *curCPtr++ = b24; - #endif - - // Write depth - #if (SW_DEPTH_BUFFER_BITS == 8) - *curDPtr++ = d8; - #elif (SW_DEPTH_BUFFER_BITS == 16) - *curDPtr++ = d16; - #elif (SW_DEPTH_BUFFER_BITS == 24) - *curDPtr++ = dByte0; - *curDPtr++ = dByte1; - *curDPtr++ = dByte2; - #endif - } - } - return; - } - - for (int i = 0; i < size; i++) - { - // Write color - #if (SW_COLOR_BUFFER_BITS == 8) - *cptr++ = packedColor; - #elif (SW_COLOR_BUFFER_BITS == 16) - *cptr++ = packedColor; - #elif (SW_COLOR_BUFFER_BITS == 24) - *cptr++ = r24; - *cptr++ = g24; - *cptr++ = b24; - #endif - - // Write depth - #if (SW_DEPTH_BUFFER_BITS == 8) - *dptr++ = d8; - #elif (SW_DEPTH_BUFFER_BITS == 16) - *dptr++ = d16; - #elif (SW_DEPTH_BUFFER_BITS == 24) - *dptr++ = dByte0; - *dptr++ = dByte1; - *dptr++ = dByte2; - #endif - } -} - -#define DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(name, DST_PTR_T) \ +#define DEFINE_FRAMEBUFFER_COPY_BEGIN(name, DST_PTR_T) \ static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \ { \ const void *src = RLSW.framebuffer.color; \ @@ -1499,23 +1493,13 @@ static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST uint8_t color[4]; \ sw_framebuffer_read_color8(color, src); \ -#define DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(name, DST_PTR_T) \ -static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \ -{ \ - const void *src = RLSW.framebuffer.color; \ - \ - for (int iy = y; iy < h; iy++) { \ - for (int ix = x; ix < w; ix++) { \ - float color[4]; \ - sw_framebuffer_read_color(color, src); \ - #define DEFINE_FRAMEBUFFER_COPY_END() \ - sw_framebuffer_inc_const_color_addr(&src); \ + INC_COLOR_PTR(src); \ } \ } \ } -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYSCALE, uint8_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(GRAYSCALE, uint8_t) { // NTSC grayscale conversion: Y = 0.299R + 0.587G + 0.114B uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000); @@ -1523,7 +1507,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYSCALE, uint8_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYALPHA, uint8_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(GRAYALPHA, uint8_t) { // Convert RGB to grayscale using NTSC formula uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000); @@ -1535,7 +1519,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(GRAYALPHA, uint8_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G6B5, uint16_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(R5G6B5, uint16_t) { // Convert 8-bit RGB to 5:6:5 format uint8_t r5 = (color[0]*31 + 127)/255; @@ -1552,7 +1536,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G6B5, uint16_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8, uint8_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(R8G8B8, uint8_t) { #if SW_GL_FRAMEBUFFER_COPY_BGRA dst[0] = color[2]; @@ -1568,7 +1552,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8, uint8_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G5B5A1, uint16_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(R5G5B5A1, uint16_t) { uint8_t r5 = (color[0]*31 + 127)/255; uint8_t g5 = (color[1]*31 + 127)/255; @@ -1585,7 +1569,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R5G5B5A1, uint16_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R4G4B4A4, uint16_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(R4G4B4A4, uint16_t) { uint8_t r4 = (color[0]*15 + 127)/255; uint8_t g4 = (color[1]*15 + 127)/255; @@ -1602,7 +1586,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R4G4B4A4, uint16_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8A8, uint8_t) +DEFINE_FRAMEBUFFER_COPY_BEGIN(R8G8B8A8, uint8_t) { #if SW_GL_FRAMEBUFFER_COPY_BGRA dst[0] = color[2]; @@ -1619,87 +1603,7 @@ DEFINE_FRAMEBUFFER_COPY_U32_BEGIN(R8G8B8A8, uint8_t) } DEFINE_FRAMEBUFFER_COPY_END() -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32, float) -{ - dst[0] = color[0]; - dst++; -} -DEFINE_FRAMEBUFFER_COPY_END() - -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32G32B32, float) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = color[2]; - dst[1] = color[1]; - dst[2] = color[0]; -#else // RGBA - dst[0] = color[0]; - dst[1] = color[1]; - dst[2] = color[2]; -#endif - - dst += 3; -} -DEFINE_FRAMEBUFFER_COPY_END() - -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R32G32B32A32, float) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = color[2]; - dst[1] = color[1]; - dst[2] = color[0]; -#else // RGBA - dst[0] = color[0]; - dst[1] = color[1]; - dst[2] = color[2]; -#endif - dst[3] = color[3]; - - dst += 4; -} -DEFINE_FRAMEBUFFER_COPY_END() - -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16, sw_half_t) -{ - dst[0] = sw_f16_from_f32(color[0]); - dst++; -} -DEFINE_FRAMEBUFFER_COPY_END() - -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16G16B16, sw_half_t) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = sw_f16_from_f32(color[2]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[0]); -#else // RGBA - dst[0] = sw_f16_from_f32(color[0]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[2]); -#endif - - dst += 3; -} -DEFINE_FRAMEBUFFER_COPY_END() - -DEFINE_FRAMEBUFFER_COPY_F32_BEGIN(R16G16B16A16, sw_half_t) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = sw_f16_from_f32(color[2]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[0]); -#else // RGBA - dst[0] = sw_f16_from_f32(color[0]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[2]); -#endif - dst[3] = sw_f16_from_f32(color[3]); - - dst += 4; -} -DEFINE_FRAMEBUFFER_COPY_END() - -#define DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(name, DST_PTR_T) \ +#define DEFINE_FRAMEBUFFER_BLIT_BEGIN(name, DST_PTR_T) \ static inline void sw_framebuffer_blit_to_##name( \ int xDst, int yDst, int wDst, int hDst, \ int xSrc, int ySrc, int wSrc, int hSrc, \ @@ -1708,56 +1612,33 @@ static inline void sw_framebuffer_blit_to_##name( const uint8_t *srcBase = (uint8_t*)RLSW.framebuffer.color; \ int fbWidth = RLSW.framebuffer.width; \ \ - uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ - uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \ + uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ + uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \ \ for (int dy = 0; dy < hDst; dy++) { \ - uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \ + uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \ int sy = yFix >> 16; \ \ for (int dx = 0; dx < wDst; dx++) { \ - uint32_t xFix = dx*xScale; \ + uint32_t xFix = dx*xScale; \ int sx = xFix >> 16; \ - const void *srcPtr = sw_framebuffer_get_color_addr(srcBase, sy*fbWidth + sx); \ + const void *srcPtr = GET_COLOR_PTR(srcBase, sy*fbWidth + sx); \ uint8_t color[4]; \ sw_framebuffer_read_color8(color, srcPtr); \ -#define DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(name, DST_PTR_T) \ -static inline void sw_framebuffer_blit_to_##name( \ - int xDst, int yDst, int wDst, int hDst, \ - int xSrc, int ySrc, int wSrc, int hSrc, \ - DST_PTR_T *dst) \ -{ \ - const uint8_t *srcBase = (uint8_t *)RLSW.framebuffer.color; \ - int fbWidth = RLSW.framebuffer.width; \ - \ - uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ - uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \ - \ - for (int dy = 0; dy < hDst; dy++) { \ - uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \ - int sy = yFix >> 16; \ - \ - for (int dx = 0; dx < wDst; dx++) { \ - uint32_t xFix = dx*xScale; \ - int sx = xFix >> 16; \ - const void *srcPtr = sw_framebuffer_get_color_addr(srcBase, sy*fbWidth + sx); \ - float color[4]; \ - sw_framebuffer_read_color(color, srcPtr); \ - #define DEFINE_FRAMEBUFFER_BLIT_END() \ } \ } \ } -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(GRAYSCALE, uint8_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(GRAYSCALE, uint8_t) { uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000); *dst++ = gray; } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(GRAYALPHA, uint8_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(GRAYALPHA, uint8_t) { uint8_t gray = (uint8_t)((color[0]*299 + color[1]*587 + color[2]*114 + 500)/1000); @@ -1768,7 +1649,7 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(GRAYALPHA, uint8_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G6B5, uint16_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(R5G6B5, uint16_t) { uint8_t r5 = (color[0]*31 + 127)/255; uint8_t g6 = (color[1]*63 + 127)/255; @@ -1784,7 +1665,7 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G6B5, uint16_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8, uint8_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(R8G8B8, uint8_t) { #if SW_GL_FRAMEBUFFER_COPY_BGRA dst[0] = color[2]; @@ -1800,7 +1681,7 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8, uint8_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G5B5A1, uint16_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(R5G5B5A1, uint16_t) { uint8_t r5 = (color[0]*31 + 127)/255; uint8_t g5 = (color[1]*31 + 127)/255; @@ -1817,7 +1698,7 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R5G5B5A1, uint16_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R4G4B4A4, uint16_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(R4G4B4A4, uint16_t) { uint8_t r4 = (color[0]*15 + 127)/255; uint8_t g4 = (color[1]*15 + 127)/255; @@ -1834,7 +1715,7 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R4G4B4A4, uint16_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8A8, uint8_t) +DEFINE_FRAMEBUFFER_BLIT_BEGIN(R8G8B8A8, uint8_t) { #if SW_GL_FRAMEBUFFER_COPY_BGRA dst[0] = color[2]; @@ -1851,86 +1732,6 @@ DEFINE_FRAMEBUFFER_BLIT_U32_BEGIN(R8G8B8A8, uint8_t) } DEFINE_FRAMEBUFFER_BLIT_END() -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32, uint8_t) -{ - dst[0] = color[0]; - dst++; -} -DEFINE_FRAMEBUFFER_BLIT_END() - -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32G32B32, float) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = color[2]; - dst[1] = color[1]; - dst[2] = color[0]; -#else // RGBA - dst[0] = color[0]; - dst[1] = color[1]; - dst[2] = color[2]; -#endif - - dst += 3; -} -DEFINE_FRAMEBUFFER_BLIT_END() - -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R32G32B32A32, float) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = color[2]; - dst[1] = color[1]; - dst[2] = color[0]; -#else // RGBA - dst[0] = color[0]; - dst[1] = color[1]; - dst[2] = color[2]; -#endif - dst[3] = color[3]; - - dst += 4; -} -DEFINE_FRAMEBUFFER_BLIT_END() - -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16, sw_half_t) -{ - dst[0] = sw_f16_from_f32(color[0]); - dst++; -} -DEFINE_FRAMEBUFFER_BLIT_END() - -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16G16B16, sw_half_t) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = sw_f16_from_f32(color[2]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[0]); -#else // RGBA - dst[0] = sw_f16_from_f32(color[0]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[2]); -#endif - - dst += 3; -} -DEFINE_FRAMEBUFFER_BLIT_END() - -DEFINE_FRAMEBUFFER_BLIT_F32_BEGIN(R16G16B16A16, sw_half_t) -{ -#if SW_GL_FRAMEBUFFER_COPY_BGRA - dst[0] = sw_f16_from_f32(color[2]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[0]); -#else // RGBA - dst[0] = sw_f16_from_f32(color[0]); - dst[1] = sw_f16_from_f32(color[1]); - dst[2] = sw_f16_from_f32(color[2]); -#endif - dst[3] = sw_f16_from_f32(color[3]); - - dst += 4; -} -DEFINE_FRAMEBUFFER_BLIT_END() - // Pixel format management functions static inline int sw_get_pixel_format(SWformat format, SWtype type) @@ -1985,210 +1786,178 @@ static inline int sw_get_pixel_format(SWformat format, SWtype type) return SW_PIXELFORMAT_UNKNOWN; } -int sw_get_pixel_bytes(sw_pixelformat_t format) +static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t offset, sw_pixelformat_t format) { - int bpp = 0; - switch (format) { - case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: bpp = 1; break; + case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: + { + uint8_t gray = ((const uint8_t*)pixels)[offset]; + color[0] = gray; + color[1] = gray; + color[2] = gray; + color[3] = 255; + break; + } case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: + { + const uint8_t *src = &((const uint8_t*)pixels)[offset*2]; + color[0] = src[0]; + color[1] = src[0]; + color[2] = src[0]; + color[3] = src[1]; + break; + } case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: + { + uint16_t pixel = ((const uint16_t*)pixels)[offset]; + color[0] = ((pixel >> 11) & 0x1F)*255/31; // R (5 bits) + color[1] = ((pixel >> 5) & 0x3F)*255/63; // G (6 bits) + color[2] = (pixel & 0x1F)*255/31; // B (5 bits) + color[3] = 255; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: + { + const uint8_t *src = &((const uint8_t*)pixels)[offset*3]; + color[0] = src[0]; + color[1] = src[1]; + color[2] = src[2]; + color[3] = 255; + break; + } case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: - case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: bpp = 2; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: bpp = 4; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: bpp = 3; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: bpp = 4; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: bpp = 4*3; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: bpp = 4*4; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: bpp = 2; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: bpp = 2*3; break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: bpp = 2*4; break; - default: break; - } - - return bpp; -} - -static inline void sw_get_pixel_grayscale(float *color, const void *pixels, uint32_t offset) -{ - float gray = (float)((uint8_t *)pixels)[offset]*(1.0f/255); - - color[0] = gray; - color[1] = gray; - color[2] = gray; - color[3] = 1.0f; -} - -static inline void sw_get_pixel_red_16(float *color, const void *pixels, uint32_t offset) -{ - float value = sw_f16_to_f32(((sw_half_t *)pixels)[offset]); - - color[0] = value; - color[1] = value; - color[2] = value; - color[3] = 1.0f; -} - -static inline void sw_get_pixel_red_32(float *color, const void *pixels, uint32_t offset) -{ - float value = ((float *)pixels)[offset]; - - color[0] = value; - color[1] = value; - color[2] = value; - color[3] = 1.0f; -} - -static inline void sw_get_pixel_grayscale_alpha(float *color, const void *pixels, uint32_t offset) -{ - const uint8_t *pixelData = (const uint8_t *)pixels + 2*offset; - - color[0] = color[1] = color[2] = (float)pixelData[0]*(1.0f/255); - color[3] = (float)pixelData[1]*(1.0f/255); -} - -static inline void sw_get_pixel_rgb_565(float *color, const void *pixels, uint32_t offset) -{ - uint16_t pixel = ((uint16_t *)pixels)[offset]; - - color[0] = (float)((pixel & 0xF800) >> 11)/31; - color[1] = (float)((pixel & 0x7E0) >> 5)/63; - color[2] = (float)(pixel & 0x1F)/31; - color[3] = 1.0f; -} - -static inline void sw_get_pixel_rgb_888(float *color, const void *pixels, uint32_t offset) -{ - const uint8_t *pixel = (const uint8_t *)pixels + 3*offset; - - color[0] = (float)pixel[0]*(1.0f/255); - color[1] = (float)pixel[1]*(1.0f/255); - color[2] = (float)pixel[2]*(1.0f/255); - color[3] = 1.0f; -} - -static inline void sw_get_pixel_rgb_161616(float *color, const void *pixels, uint32_t offset) -{ - const sw_half_t *pixel = (sw_half_t *)pixels + 3*offset; - - color[0] = sw_f16_to_f32(pixel[0]); - color[1] = sw_f16_to_f32(pixel[1]); - color[2] = sw_f16_to_f32(pixel[2]); - color[3] = 1.0f; -} - -static inline void sw_get_pixel_rgb_323232(float *color, const void *pixels, uint32_t offset) -{ - const float *pixel = (float *)pixels + 3*offset; - - color[0] = pixel[0]; - color[1] = pixel[1]; - color[2] = pixel[2]; - color[3] = 1.0f; -} - -static inline void sw_get_pixel_rgba_5551(float *color, const void *pixels, uint32_t offset) -{ - uint16_t pixel = ((uint16_t *)pixels)[offset]; - - color[0] = (float)((pixel & 0xF800) >> 11)/31; - color[1] = (float)((pixel & 0x7C0) >> 6)/31; - color[2] = (float)((pixel & 0x3E) >> 1)/31; - color[3] = (float)(pixel & 0x1); -} - -static inline void sw_get_pixel_rgba_4444(float *color, const void *pixels, uint32_t offset) -{ - uint16_t pixel = ((uint16_t *)pixels)[offset]; - - color[0] = (float)((pixel & 0xF000) >> 12)/15; - color[1] = (float)((pixel & 0xF00) >> 8)/15; - color[2] = (float)((pixel & 0xF0) >> 4)/15; - color[3] = (float)(pixel & 0xF)/15; -} - -static inline void sw_get_pixel_rgba_8888(float *color, const void *pixels, uint32_t offset) -{ - const uint8_t *pixel = (uint8_t *)pixels + 4*offset; - - color[0] = (float)pixel[0]*(1.0f/255); - color[1] = (float)pixel[1]*(1.0f/255); - color[2] = (float)pixel[2]*(1.0f/255); - color[3] = (float)pixel[3]*(1.0f/255); -} - -static inline void sw_get_pixel_rgba_16161616(float *color, const void *pixels, uint32_t offset) -{ - const sw_half_t *pixel = (sw_half_t *)pixels + 4*offset; - - color[0] = sw_f16_to_f32(pixel[0]); - color[1] = sw_f16_to_f32(pixel[1]); - color[2] = sw_f16_to_f32(pixel[2]); - color[3] = sw_f16_to_f32(pixel[3]); -} - -static inline void sw_get_pixel_rgba_32323232(float *color, const void *pixels, uint32_t offset) -{ - const float *pixel = (float *)pixels + 4*offset; - - color[0] = pixel[0]; - color[1] = pixel[1]; - color[2] = pixel[2]; - color[3] = pixel[3]; -} - -static inline void sw_get_pixel(float *color, const void *pixels, uint32_t offset, sw_pixelformat_t format) -{ - switch (format) - { - case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_get_pixel_grayscale(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: sw_get_pixel_grayscale_alpha(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5: sw_get_pixel_rgb_565(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8: sw_get_pixel_rgb_888(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_get_pixel_rgba_5551(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_get_pixel_rgba_4444(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_get_pixel_rgba_8888(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_get_pixel_red_32(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_get_pixel_rgb_323232(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_get_pixel_rgba_32323232(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_get_pixel_red_16(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_get_pixel_rgb_161616(color, pixels, offset); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_get_pixel_rgba_16161616(color, pixels, offset); break; - case SW_PIXELFORMAT_UNKNOWN: break; - default: break; + { + uint16_t pixel = ((const uint16_t*)pixels)[offset]; + color[0] = ((pixel >> 11) & 0x1F)*255/31; // R (5 bits) + color[1] = ((pixel >> 6) & 0x1F)*255/31; // G (5 bits) + color[2] = ((pixel >> 1) & 0x1F)*255/31; // B (5 bits) + color[3] = (pixel & 0x01)*255; // A (1 bit) + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: + { + uint16_t pixel = ((const uint16_t*)pixels)[offset]; + color[0] = ((pixel >> 12) & 0x0F)*255/15; // R (4 bits) + color[1] = ((pixel >> 8) & 0x0F)*255/15; // G (4 bits) + color[2] = ((pixel >> 4) & 0x0F)*255/15; // B (4 bits) + color[3] = (pixel & 0x0F)*255/15; // A (4 bits) + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: + { + const uint8_t *src = &((const uint8_t*)pixels)[offset*4]; + color[0] = src[0]; + color[1] = src[1]; + color[2] = src[2]; + color[3] = src[3]; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R32: + { + float val = ((const float*)pixels)[offset]; + uint8_t gray = (uint8_t)(val*255.0f); + color[0] = gray; + color[1] = gray; + color[2] = gray; + color[3] = 255; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: + { + const float *src = &((const float*)pixels)[offset*3]; + color[0] = (uint8_t)(src[0]*255.0f); + color[1] = (uint8_t)(src[1]*255.0f); + color[2] = (uint8_t)(src[2]*255.0f); + color[3] = 255; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: + { + const float *src = &((const float*)pixels)[offset*4]; + color[0] = (uint8_t)(src[0]*255.0f); + color[1] = (uint8_t)(src[1]*255.0f); + color[2] = (uint8_t)(src[2]*255.0f); + color[3] = (uint8_t)(src[3]*255.0f); + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R16: + { + uint16_t val = ((const uint16_t*)pixels)[offset]; + uint8_t gray = sw_half_to_float(val)/255.0f; + color[0] = gray; + color[1] = gray; + color[2] = gray; + color[3] = 255; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: + { + const uint16_t *src = &((const uint16_t*)pixels)[offset*3]; + color[0] = sw_half_to_float(src[0])/255.0f; + color[1] = sw_half_to_float(src[1])/255.0f; + color[2] = sw_half_to_float(src[2])/255.0f; + color[3] = 255; + break; + } + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: + { + const uint16_t *src = &((const uint16_t*)pixels)[offset*4]; + color[0] = sw_half_to_float(src[0])/255.0f; + color[1] = sw_half_to_float(src[1])/255.0f; + color[2] = sw_half_to_float(src[2])/255.0f; + color[3] = sw_half_to_float(src[3])/255.0f; + break; + } + case SW_PIXELFORMAT_UNKNOWN: + default: + { + color[0] = 0; + color[1] = 0; + color[2] = 0; + color[3] = 0; + break; + } } } // Texture sampling functionality +static inline void sw_texture_fetch(float* color, const sw_texture_t* tex, int x, int y) +{ + sw_float_from_unorm8_simd(color, &tex->pixels[4*(y*tex->width + x)]); +} + static inline void sw_texture_sample_nearest(float *color, const sw_texture_t *tex, float u, float v) { u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u); v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v); - int x = u*tex->width, y = v*tex->height; + int x = u*tex->width; + int y = v*tex->height; - sw_get_pixel(color, tex->pixels.cptr, y*tex->width + x, tex->format); + sw_texture_fetch(color, tex, x, y); } static inline void sw_texture_sample_linear(float *color, const sw_texture_t *tex, float u, float v) { - // TODO: REVIEW: With a bit more cleverness we could clearly reduce the + // TODO: With a bit more cleverness we could clearly reduce the // number of operations here, but for now it works fine. - float xf = u*tex->width - 0.5f; - float yf = v*tex->height - 0.5f; + float xf = (u*tex->width) - 0.5f; + float yf = (v*tex->height) - 0.5f; - int x0 = (int)floorf(xf); - int y0 = (int)floorf(yf); + float fx = sw_fract(xf); + float fy = sw_fract(yf); - float fx = xf - x0; - float fy = yf - y0; + int x0 = (int)xf; + int y0 = (int)yf; int x1 = x0 + 1; int y1 = y0 + 1; + // NOTE: If the textures are POT we could avoid the division for SW_REPEAT + if (tex->sWrap == SW_CLAMP) { x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0; @@ -2212,10 +1981,10 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te } float c00[4], c10[4], c01[4], c11[4]; - sw_get_pixel(c00, tex->pixels.cptr, y0*tex->width + x0, tex->format); - sw_get_pixel(c10, tex->pixels.cptr, y0*tex->width + x1, tex->format); - sw_get_pixel(c01, tex->pixels.cptr, y1*tex->width + x0, tex->format); - sw_get_pixel(c11, tex->pixels.cptr, y1*tex->width + x1, tex->format); + sw_texture_fetch(c00, tex, x0, y0); + sw_texture_fetch(c10, tex, x1, y0); + sw_texture_fetch(c01, tex, x0, y1); + sw_texture_fetch(c11, tex, x1, y1); for (int i = 0; i < 4; i++) { @@ -2512,23 +2281,23 @@ static inline void sw_triangle_clip_and_project(void) // Calculation of the reciprocal of W for normalization // as well as perspective-correct attributes - const float invW = 1.0f/v->homogeneous[3]; - v->homogeneous[3] = invW; + const float wRcp = 1.0f/v->homogeneous[3]; + v->homogeneous[3] = wRcp; // Division of XYZ coordinates by weight - v->homogeneous[0] *= invW; - v->homogeneous[1] *= invW; - v->homogeneous[2] *= invW; + v->homogeneous[0] *= wRcp; + v->homogeneous[1] *= wRcp; + v->homogeneous[2] *= wRcp; // Division of texture coordinates (perspective-correct) - v->texcoord[0] *= invW; - v->texcoord[1] *= invW; + v->texcoord[0] *= wRcp; + v->texcoord[1] *= wRcp; // Division of colors (perspective-correct) - v->color[0] *= invW; - v->color[1] *= invW; - v->color[2] *= invW; - v->color[3] *= invW; + v->color[0] *= wRcp; + v->color[1] *= wRcp; + v->color[2] *= wRcp; + v->color[3] *= wRcp; // Transformation to screen space sw_project_ndc_to_screen(v->screen, v->homogeneous); @@ -2583,8 +2352,8 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, } \ \ /* Pre-calculate the starting pointers for the framebuffer row */ \ - void *cptr = sw_framebuffer_get_color_addr(RLSW.framebuffer.color, y*RLSW.framebuffer.width + xStart); \ - void *dptr = sw_framebuffer_get_depth_addr(RLSW.framebuffer.depth, y*RLSW.framebuffer.width + xStart); \ + void *cptr = GET_COLOR_PTR(RLSW.framebuffer.color, y*RLSW.framebuffer.width + xStart); \ + void *dptr = GET_DEPTH_PTR(RLSW.framebuffer.depth, y*RLSW.framebuffer.width + xStart); \ \ /* Scanline rasterization */ \ for (int x = xStart; x < xEnd; x++) \ @@ -2624,12 +2393,7 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, { \ float dstColor[4]; \ sw_framebuffer_read_color(dstColor, cptr); \ - \ sw_blend_colors(dstColor, srcColor); \ - dstColor[0] = sw_saturate(dstColor[0]); \ - dstColor[1] = sw_saturate(dstColor[1]); \ - dstColor[2] = sw_saturate(dstColor[2]); \ - \ sw_framebuffer_write_color(cptr, dstColor); \ } \ else \ @@ -2651,8 +2415,8 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, v += dvDx; \ } \ \ - sw_framebuffer_inc_color_addr(&cptr); \ - sw_framebuffer_inc_depth_addr(&dptr); \ + INC_COLOR_PTR(cptr); \ + INC_DEPTH_PTR(dptr); \ } \ } @@ -2777,13 +2541,17 @@ static inline void sw_triangle_render(void) } \ } - if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND) - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH) - else if (SW_STATE_CHECK(SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND) - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX) + uint32_t state = RLSW.stateFlags; + if (RLSW.currentTexture == 0) state &= ~SW_STATE_TEXTURE_2D; + if ((RLSW.srcFactor == SW_ONE) && (RLSW.dstFactor == SW_ZERO)) state &= ~SW_STATE_BLEND; + + if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH) + else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX) else TRIANGLE_RASTER(sw_triangle_raster) #undef TRIANGLE_RASTER @@ -2859,23 +2627,23 @@ static inline void sw_quad_clip_and_project(void) // Calculation of the reciprocal of W for normalization // as well as perspective-correct attributes - const float invW = 1.0f/v->homogeneous[3]; - v->homogeneous[3] = invW; + const float wRcp = 1.0f/v->homogeneous[3]; + v->homogeneous[3] = wRcp; // Division of XYZ coordinates by weight - v->homogeneous[0] *= invW; - v->homogeneous[1] *= invW; - v->homogeneous[2] *= invW; + v->homogeneous[0] *= wRcp; + v->homogeneous[1] *= wRcp; + v->homogeneous[2] *= wRcp; // Division of texture coordinates (perspective-correct) - v->texcoord[0] *= invW; - v->texcoord[1] *= invW; + v->texcoord[0] *= wRcp; + v->texcoord[1] *= wRcp; // Division of colors (perspective-correct) - v->color[0] *= invW; - v->color[1] *= invW; - v->color[2] *= invW; - v->color[3] *= invW; + v->color[0] *= wRcp; + v->color[1] *= wRcp; + v->color[2] *= wRcp; + v->color[3] *= wRcp; // Transformation to screen space sw_project_ndc_to_screen(v->screen, v->homogeneous); @@ -2908,76 +2676,40 @@ static inline bool sw_quad_is_axis_aligned(void) static inline void sw_quad_sort_cw(const sw_vertex_t* *output) { - // Sort 4 quad vertices into clockwise order with fixed layout: - // - // v0 -- v1 - // | | - // v3 -- v2 - // - // The goal is: - // - v0: top-left (minimum Y, then minimum X) - // - v1: top-right (minimum Y row, maximum X) - // - v2: bottom-right (maximum Y, maximum X) - // - v3: bottom-left (maximum Y, minimum X) const sw_vertex_t *input = RLSW.vertexBuffer; - // Separate vertices into top and bottom based on Y-coordinate - const sw_vertex_t *top[2] = {NULL, NULL}; - const sw_vertex_t *bottom[2] = {NULL, NULL}; - int topCount = 0, bottomCount = 0; + // Calculate the centroid of the quad + float cx = (input[0].screen[0] + input[1].screen[0] + + input[2].screen[0] + input[3].screen[0])*0.25f; + float cy = (input[0].screen[1] + input[1].screen[1] + + input[2].screen[1] + input[3].screen[1])*0.25f; - // Find minimum and maximum Y - float minY = input[0].screen[1]; - float maxY = input[0].screen[1]; + // Calculate the angle of each vertex relative to the center + // and assign them directly to their correct position + const sw_vertex_t *corners[4] = { 0 }; - for (int i = 1; i < 4; i++) - { - if (input[i].screen[1] < minY) minY = input[i].screen[1]; - if (input[i].screen[1] > maxY) maxY = input[i].screen[1]; - } - - // Separate vertices based on Y-coordinate for (int i = 0; i < 4; i++) { - if ((input[i].screen[1] == minY) && (topCount < 2)) top[topCount++] = &input[i]; - else if ((input[i].screen[1] == maxY) && (bottomCount < 2)) bottom[bottomCount++] = &input[i]; + float dx = input[i].screen[0] - cx; + float dy = input[i].screen[1] - cy; + + // Determine the quadrant (clockwise from top-left) + // top-left: dx < 0, dy < 0 + // top-right: dx >= 0, dy < 0 + // bottom-right: dx >= 0, dy >= 0 + // bottom-left: dx < 0, dy >= 0 + + int idx; + if (dy < 0) idx = (dx < 0)? 0 : 1; // Top row + else idx = (dx < 0)? 3 : 2; // Bottom row + + corners[idx] = &input[i]; } - // If we don't have enough top/bottom vertices (e.g., Y values are all different), - // classify vertices as top or bottom based on whether they're closer to minY or maxY - for (int i = 0; i < 4; i++) - { - if ((topCount < 2) && (&input[i] != top[0]) && (&input[i] != bottom[0]) && (&input[i] != bottom[1])) - { - if (fabsf(input[i].screen[1] - minY) <= fabsf(input[i].screen[1] - maxY)) top[topCount++] = &input[i]; - } - if ((bottomCount < 2) && (&input[i] != top[0]) && (&input[i] != top[1]) && (&input[i] != bottom[0])) - { - if (fabsf(input[i].screen[1] - maxY) < fabsf(input[i].screen[1] - minY)) bottom[bottomCount++] = &input[i]; - } - } - - // Sort top vertices by X (left to right) - if ((topCount == 2) && (top[0]->screen[0] > top[1]->screen[0])) - { - const sw_vertex_t *temp = top[0]; - top[0] = top[1]; - top[1] = temp; - } - - // Sort bottom vertices by X (left to right) - if ((bottomCount == 2) && (bottom[0]->screen[0] > bottom[1]->screen[0])) - { - const sw_vertex_t *temp = bottom[0]; - bottom[0] = bottom[1]; - bottom[1] = temp; - } - - // Assign vertices in clockwise order as per the required layout - output[0] = top[0]; // v0: top-left - output[1] = top[topCount-1]; // v1: top-right - output[2] = bottom[bottomCount-1]; // v2: bottom-right - output[3] = bottom[0]; // v3: bottom-left + output[0] = corners[0]; // top-left + output[1] = corners[1]; // top-right + output[2] = corners[2]; // bottom-right + output[3] = corners[3]; // bottom-left } // TODO: REVIEW: Could a perfectly aligned quad, where one of the four points has a different depth, @@ -3052,8 +2784,8 @@ static inline void FUNC_NAME(void) \ for (int y = yMin; y < yMax; y++) \ { \ - void *cptr = sw_framebuffer_get_color_addr(cDstBase, y*wDst + xMin); \ - void *dptr = sw_framebuffer_get_depth_addr(dDstBase, y*wDst + xMin); \ + void *cptr = GET_COLOR_PTR(cDstBase, y*wDst + xMin); \ + void *dptr = GET_DEPTH_PTR(dDstBase, y*wDst + xMin); \ \ float z = zScanline; \ float u = uScanline; \ @@ -3101,13 +2833,7 @@ static inline void FUNC_NAME(void) { \ float dstColor[4]; \ sw_framebuffer_read_color(dstColor, cptr); \ - \ sw_blend_colors(dstColor, srcColor); \ - dstColor[0] = sw_saturate(dstColor[0]); \ - dstColor[1] = sw_saturate(dstColor[1]); \ - dstColor[2] = sw_saturate(dstColor[2]); \ - dstColor[3] = sw_saturate(dstColor[3]); \ - \ sw_framebuffer_write_color(cptr, dstColor); \ } \ else sw_framebuffer_write_color(cptr, srcColor); \ @@ -3125,8 +2851,8 @@ static inline void FUNC_NAME(void) v += tcDx[1]; \ } \ \ - sw_framebuffer_inc_color_addr(&cptr); \ - sw_framebuffer_inc_depth_addr(&dptr); \ + INC_COLOR_PTR(cptr); \ + INC_DEPTH_PTR(dptr); \ } \ \ zScanline += zDy; \ @@ -3163,15 +2889,19 @@ static inline void sw_quad_render(void) if (RLSW.vertexCounter < 3) return; + uint32_t state = RLSW.stateFlags; + if (RLSW.currentTexture == 0) state &= ~SW_STATE_TEXTURE_2D; + if ((RLSW.srcFactor == SW_ONE) && (RLSW.dstFactor == SW_ZERO)) state &= ~SW_STATE_BLEND; + if ((RLSW.vertexCounter == 4) && sw_quad_is_axis_aligned()) { - if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND(); - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_DEPTH_BLEND(); - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_BLEND(); - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_TEX_DEPTH(); - else if (SW_STATE_CHECK(SW_STATE_BLEND)) sw_quad_raster_axis_aligned_BLEND(); - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_DEPTH(); - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) sw_quad_raster_axis_aligned_TEX(); + if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_DEPTH_BLEND(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_DEPTH_BLEND(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) sw_quad_raster_axis_aligned_TEX_BLEND(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_TEX_DEPTH(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) sw_quad_raster_axis_aligned_BLEND(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) sw_quad_raster_axis_aligned_DEPTH(); + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) sw_quad_raster_axis_aligned_TEX(); else sw_quad_raster_axis_aligned(); return; } @@ -3189,13 +2919,13 @@ static inline void sw_quad_render(void) } \ } - if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND) - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH) - else if (SW_STATE_CHECK(SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND) - else if (SW_STATE_CHECK(SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH) - else if (SW_STATE_CHECK(SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX) + if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_TEX_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D | SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_TEX_DEPTH) + else if (SW_STATE_CHECK_EX(state, SW_STATE_BLEND)) TRIANGLE_RASTER(sw_triangle_raster_BLEND) + else if (SW_STATE_CHECK_EX(state, SW_STATE_DEPTH_TEST)) TRIANGLE_RASTER(sw_triangle_raster_DEPTH) + else if (SW_STATE_CHECK_EX(state, SW_STATE_TEXTURE_2D)) TRIANGLE_RASTER(sw_triangle_raster_TEX) else TRIANGLE_RASTER(sw_triangle_raster) #undef TRIANGLE_RASTER @@ -3310,7 +3040,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ int dy = y2 - y1; \ \ /* Handling of lines that are more horizontal or vertical */ \ - if ((dx == 0) && (dy == 0)) \ + if ((dx == 0) && (dy == 0)) \ { \ /* TODO: A point should be rendered here */ \ return; \ @@ -3366,8 +3096,8 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ for (int i = 0; i != longLen; i += sgnInc) \ { \ int offset = (y1 + i)*fbWidth + (x1 + (j >> 16)); \ - void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \ - void *cptr; \ + void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ + void *cptr = NULL; \ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3377,13 +3107,12 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ \ sw_framebuffer_write_depth(dptr, z); \ \ - cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ + cptr = GET_COLOR_PTR(cBuffer, offset); \ \ if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ sw_framebuffer_read_color(dstColor, cptr); \ - \ sw_blend_colors(dstColor, color); \ sw_framebuffer_write_color(cptr, dstColor); \ } \ @@ -3403,8 +3132,8 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ for (int i = 0; i != longLen; i += sgnInc) \ { \ int offset = (y1 + (j >> 16))*fbWidth + (x1 + i); \ - void *dptr = sw_framebuffer_get_depth_addr(dBuffer, offset); \ - void *cptr; \ + void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ + void *cptr = NULL; \ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3414,17 +3143,16 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ \ sw_framebuffer_write_depth(dptr, z); \ \ - cptr = sw_framebuffer_get_color_addr(cBuffer, offset); \ + cptr = GET_COLOR_PTR(cBuffer, offset); \ \ if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ sw_framebuffer_read_color(dstColor, cptr); \ - \ sw_blend_colors(dstColor, color); \ sw_framebuffer_write_color(cptr, dstColor); \ } \ - else sw_framebuffer_write_color(cptr, color); \ + else sw_framebuffer_write_color(cptr, color); \ \ discardB: \ j += decInc; \ @@ -3570,7 +3298,7 @@ static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \ \ int offset = y*RLSW.framebuffer.width + x; \ \ - void *dptr = sw_framebuffer_get_depth_addr(RLSW.framebuffer.depth, offset); \ + void *dptr = GET_DEPTH_PTR(RLSW.framebuffer.depth, offset); \ \ if (ENABLE_DEPTH_TEST) \ { \ @@ -3580,13 +3308,12 @@ static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \ \ sw_framebuffer_write_depth(dptr, z); \ \ - void *cptr = sw_framebuffer_get_color_addr(RLSW.framebuffer.color, offset); \ + void *cptr = GET_COLOR_PTR(RLSW.framebuffer.color, offset); \ \ if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ sw_framebuffer_read_color(dstColor, cptr); \ - \ sw_blend_colors(dstColor, color); \ sw_framebuffer_write_color(cptr, dstColor); \ } \ @@ -3724,7 +3451,7 @@ static inline bool sw_is_texture_valid(uint32_t id) if (id == 0) valid = false; else if (id >= SW_MAX_TEXTURES) valid = false; - else if (RLSW.loadedTextures[id].pixels.cptr == 0) valid = false; + else if (RLSW.loadedTextures[id].pixels == NULL) valid = false; return true; } @@ -3872,26 +3599,24 @@ bool swInit(int w, int h) RLSW.polyMode = SW_FILL; RLSW.cullFace = SW_BACK; - static const float defTex[3*2*2] = { - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, + static uint32_t defaultTex[3*2*2] = { + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF, + 0xFFFFFFFF }; - RLSW.loadedTextures[0].pixels.cptr = defTex; + RLSW.loadedTextures[0].pixels = (uint8_t*)defaultTex; RLSW.loadedTextures[0].width = 2; RLSW.loadedTextures[0].height = 2; RLSW.loadedTextures[0].wMinus1 = 1; RLSW.loadedTextures[0].hMinus1 = 1; - RLSW.loadedTextures[0].format = SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32; RLSW.loadedTextures[0].minFilter = SW_NEAREST; RLSW.loadedTextures[0].magFilter = SW_NEAREST; RLSW.loadedTextures[0].sWrap = SW_REPEAT; RLSW.loadedTextures[0].tWrap = SW_REPEAT; RLSW.loadedTextures[0].tx = 0.5f; RLSW.loadedTextures[0].ty = 0.5f; - RLSW.loadedTextures[0].copy = false; RLSW.loadedTextureCount = 1; @@ -3900,10 +3625,13 @@ bool swInit(int w, int h) void swClose(void) { + // NOTE: Starts at texture 1, texture 0 does not have to be freed for (int i = 1; i < RLSW.loadedTextureCount; i++) { - sw_texture_t *texture = &RLSW.loadedTextures[i]; - if (sw_is_texture_valid(i) && texture->copy) SW_FREE(texture->pixels.ptr); + if (sw_is_texture_valid(i)) + { + SW_FREE(RLSW.loadedTextures[i].pixels); + } } SW_FREE(RLSW.framebuffer.color); @@ -3950,13 +3678,16 @@ void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_copy_to_R5G5B5A1(x, y, w, h, (uint16_t *)pixels); break; case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_copy_to_R4G4B4A4(x, y, w, h, (uint16_t *)pixels); break; case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_copy_to_R8G8B8A8(x, y, w, h, (uint8_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_copy_to_R32(x, y, w, h, (float *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_copy_to_R32G32B32(x, y, w, h, (float *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_copy_to_R32G32B32A32(x, y, w, h, (float *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_copy_to_R16(x, y, w, h, (sw_half_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_copy_to_R16G16B16(x, y, w, h, (sw_half_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_copy_to_R16G16B16A16(x, y, w, h, (sw_half_t *)pixels); break; - default: RLSW.errCode = SW_INVALID_ENUM; break; + // Below: not implemented + case SW_PIXELFORMAT_UNCOMPRESSED_R32: + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: + case SW_PIXELFORMAT_UNCOMPRESSED_R16: + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: + default: + RLSW.errCode = SW_INVALID_ENUM; + break; } } @@ -3991,13 +3722,16 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr case SW_PIXELFORMAT_UNCOMPRESSED_R5G5B5A1: sw_framebuffer_blit_to_R5G5B5A1(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break; case SW_PIXELFORMAT_UNCOMPRESSED_R4G4B4A4: sw_framebuffer_blit_to_R4G4B4A4(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint16_t *)pixels); break; case SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8: sw_framebuffer_blit_to_R8G8B8A8(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32: sw_framebuffer_blit_to_R32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: sw_framebuffer_blit_to_R32G32B32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (float *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: sw_framebuffer_blit_to_R32G32B32A32(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (float*)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16: sw_framebuffer_blit_to_R16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: sw_framebuffer_blit_to_R16G16B16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; - case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: sw_framebuffer_blit_to_R16G16B16A16(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (sw_half_t *)pixels); break; - default: RLSW.errCode = SW_INVALID_ENUM; break; + // Below: not implemented + case SW_PIXELFORMAT_UNCOMPRESSED_R32: + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32: + case SW_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: + case SW_PIXELFORMAT_UNCOMPRESSED_R16: + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: + case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: + default: + RLSW.errCode = SW_INVALID_ENUM; + break; } } @@ -4814,17 +4548,14 @@ void swDeleteTextures(int count, uint32_t *textures) continue; } - if (RLSW.loadedTextures[textures[i]].copy) - { - SW_FREE(RLSW.loadedTextures[textures[i]].pixels.ptr); - } + SW_FREE(RLSW.loadedTextures[textures[i]].pixels); - RLSW.loadedTextures[textures[i]].pixels.cptr = NULL; + RLSW.loadedTextures[textures[i]].pixels = NULL; RLSW.freeTextureIds[RLSW.freeTextureIdCount++] = textures[i]; } } -void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy, const void *data) +void swTexImage2D(int width, int height, SWformat format, SWtype type, const void *data) { uint32_t id = RLSW.currentTexture; @@ -4844,33 +4575,27 @@ void swTexImage2D(int width, int height, SWformat format, SWtype type, bool copy sw_texture_t *texture = &RLSW.loadedTextures[id]; - if (copy) + int size = width*height; + texture->pixels = SW_MALLOC(4*size); + + if (texture->pixels == NULL) { - int bytes = sw_get_pixel_bytes((sw_pixelformat_t)pixelFormat); - int size = bytes*width*height; - texture->pixels.ptr = SW_MALLOC(size); + RLSW.errCode = SW_STACK_OVERFLOW; // WARNING: Out of memory... + return; + } - if (texture->pixels.ptr == NULL) - { - RLSW.errCode = SW_STACK_OVERFLOW; // WARING: Out of memory... - return; - } - - for (int i = 0; i < size; i++) - { - ((uint8_t *)texture->pixels.ptr)[i] = ((uint8_t *)data)[i]; - } + for (int i = 0; i < size; i++) + { + uint32_t *dst = &((uint32_t*)texture->pixels)[i]; + sw_get_pixel((uint8_t*)dst, data, i, pixelFormat); } - else texture->pixels.cptr = data; texture->width = width; texture->height = height; texture->wMinus1 = width - 1; texture->hMinus1 = height - 1; - texture->format = (sw_pixelformat_t)pixelFormat; texture->tx = 1.0f/width; texture->ty = 1.0f/height; - texture->copy = copy; } void swTexParameteri(int param, int value) @@ -4939,7 +4664,7 @@ void swBindTexture(uint32_t id) return; } - if (RLSW.loadedTextures[id].pixels.cptr == NULL) + if (RLSW.loadedTextures[id].pixels == NULL) { RLSW.errCode = SW_INVALID_OPERATION; return; From 4bb8c89084930862b70042845166739cf058e883 Mon Sep 17 00:00:00 2001 From: Jeffery Myers Date: Sat, 25 Oct 2025 00:49:31 -0700 Subject: [PATCH 065/102] Don't undefine the versions of LoadImage that don't conflict with raylib so that the Win32 platform can use them. (#5299) --- src/platforms/rcore_desktop_win32.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 9b66f8c4b..5b67c72b0 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -49,8 +49,6 @@ #define CloseWindow CloseWindowWin32 #define Rectangle RectangleWin32 #define ShowCursor ShowCursorWin32 -#define LoadImageA LoadImageAWin32 -#define LoadImageW LoadImageWin32 #define DrawTextA DrawTextAWin32 #define DrawTextW DrawTextWin32 #define DrawTextExA DrawTextExAWin32 @@ -63,8 +61,6 @@ #undef Rectangle // raylib symbol collision #undef ShowCursor // raylib symbol collision #undef LoadImage // raylib symbol collision -#undef LoadImageA -#undef LoadImageW #undef DrawText // raylib symbol collision #undef DrawTextA #undef DrawTextW @@ -1529,7 +1525,7 @@ int InitPlatform(void) // Load user-provided icon if available // NOTE: raylib resource file defaults to GLFW_ICON id, so looking for same identifier windowClass.hIcon = LoadImageW(hInstance, L"GLFW_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); - if (!windowClass.hIcon) windowClass.hIcon = LoadImageW(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (!windowClass.hIcon) windowClass.hIcon = LoadImageW(NULL, (LPCWSTR)IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); // Register window class result = (int)RegisterClassExW(&windowClass); From dbcc5081964cb2413b32eecf2135d73e32420285 Mon Sep 17 00:00:00 2001 From: themushroompirates <59015901+themushroompirates@users.noreply.github.com> Date: Sat, 25 Oct 2025 10:41:39 +0200 Subject: [PATCH 066/102] [examples] Added `models_decals` (#5298) * Added decal models example * Code formatting to match Raylib conventions --- examples/models/models_decals.c | 573 +++ examples/models/models_decals.png | Bin 0 -> 62387 bytes .../models/resources/models/obj/character.mtl | 12 + .../models/resources/models/obj/character.obj | 3454 +++++++++++++++++ .../models/obj/character_diffuse.png | Bin 0 -> 41705 bytes examples/models/resources/raylib_logo.png | Bin 0 -> 3672 bytes 6 files changed, 4039 insertions(+) create mode 100644 examples/models/models_decals.c create mode 100644 examples/models/models_decals.png create mode 100644 examples/models/resources/models/obj/character.mtl create mode 100644 examples/models/resources/models/obj/character.obj create mode 100644 examples/models/resources/models/obj/character_diffuse.png create mode 100644 examples/models/resources/raylib_logo.png diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c new file mode 100644 index 000000000..81bbd2796 --- /dev/null +++ b/examples/models/models_decals.c @@ -0,0 +1,573 @@ +/******************************************************************************************* +* +* raylib [models] example - decals +* +* Example complexity rating: [★★★☆] 3/4 +* +* Example originally created with raylib 5.6-dev +* +* Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5) +* Based on previous work by @mrdoob +* +* 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) 2025 JP Mortiboys (@themushroompirates) and Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +#include + +#undef FLT_MAX +#define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111 + +#define MAX_DECALS 256 + +typedef struct MeshBuilder { + int vertexCount; + int vertexCapacity; + Vector3 *vertices; + Vector2 *uvs; +} MeshBuilder; + +// Utility functions +void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]); +void FreeMeshBuilder(MeshBuilder *mb); +Mesh BuildMesh(MeshBuilder *mb); + +Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); + +Mesh GenMeshDecal(Mesh inputMesh, Ray ray); + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [models] example - decals"); + + // 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, 1.0f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.6f, 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 character model + Model model = LoadModel("resources/models/obj/character.obj"); + + // Apply character skin + Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png"); // Load model texture + SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR); + model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture; // Set model diffuse texture + + + BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]); // Get mesh bounding box + + camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f); + camera.position = Vector3Scale(modelBBox.max, 1.0f); + camera.position.x *= 0.1f; + + float modelSize = fminf( + fminf(fabsf(modelBBox.max.x - modelBBox.min.x), + fabsf(modelBBox.max.y - modelBBox.min.y)), + fabsf(modelBBox.max.z - modelBBox.min.z) + ); + + camera.position = (Vector3){ 0, modelBBox.max.y * 1.2f, modelSize * 3.0f }; + + float decalSize = modelSize * .25f; + float decalOffset = 0.01f; + + Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize)); + placementCube.materials[0].maps[0].color = LIME; + + Material decalMaterial = LoadMaterialDefault(); + decalMaterial.maps[0].color = YELLOW; + + Image decalImage = LoadImage("resources/raylib_logo.png"); + ImageResizeNN(&decalImage, decalImage.width / 4, decalImage.height / 4); + Texture decalTexture = LoadTextureFromImage(decalImage); + UnloadImage(decalImage); + + SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR); + decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture; + decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE; + + // We're going to use these to build up our decal meshes + // They'll resize automatically as we go, we'll free them at the end + MeshBuilder mesh_builders[2] = { {0}, {0} }; + + bool showModel = true; + Model decalModels[MAX_DECALS] = {0}; + int decalCount = 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 + { + // Update + //---------------------------------------------------------------------------------- + + if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) { + UpdateCamera(&camera, CAMERA_THIRD_PERSON); + } + + if (IsKeyPressed(KEY_SPACE)) { + showModel = !showModel; + } + + // Display information about closest hit + RayCollision collision = { 0 }; + collision.distance = FLT_MAX; + collision.hit = false; + + // Get mouse ray + Ray ray = GetScreenToWorldRay(GetMousePosition(), camera); + + // Check ray collision against bounding box first, before trying the full ray-mesh test + RayCollision boxHitInfo = GetRayCollisionBox(ray, modelBBox); + + if ((boxHitInfo.hit) && decalCount < MAX_DECALS) + { + // Check ray collision against model meshes + RayCollision meshHitInfo = { 0 }; + for (int m = 0; m < model.meshCount; m++) + { + // NOTE: We consider the model.transform for the collision check but + // it can be checked against any transform Matrix, used when checking against same + // model drawn multiple times with multiple transforms + meshHitInfo = GetRayCollisionMesh(ray, model.meshes[m], model.transform); + if (meshHitInfo.hit) + { + // Save the closest hit mesh + if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo; + } + } + + if (meshHitInfo.hit) + { + collision = meshHitInfo; + } + } + + // -------------- + + if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && decalCount < MAX_DECALS) + { + + // Create the transformation to project the decal + Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); + Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0}); + + // Spin the placement around a bit + splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD * ((float)GetRandomValue(-180, 180)))); + + Matrix splatInv = MatrixInvert(splat); + + // Reset the mesh builders + mesh_builders[0].vertexCount = 0; + mesh_builders[1].vertexCount = 0; + + // We'll be flip-flopping between the two mesh builders + // Reading from one and writing to the other, then swapping + int mb_index = 0; + + // First pass, just get any triangle inside the bounding box + // (for each mesh of the model) + for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++) { + Mesh mesh = model.meshes[meshIndex]; + for (int tri = 0; tri < mesh.triangleCount; tri++) + { + Vector3 vertices[3]; + + // The way we calculate the vertices of the mesh triangle + // depend on whether the mesh vertices are indexed or not + if (mesh.indices == 0) + { + for (int v = 0; v < 3; v++) { + vertices[v] = (Vector3) { + mesh.vertices[3*3*tri + 3*v + 0], + mesh.vertices[3*3*tri + 3*v + 1], + mesh.vertices[3*3*tri + 3*v + 2] + }; + } + } + else + { + for (int v = 0; v < 3; v++) + { + vertices[v] = (Vector3) { + mesh.vertices[ 3*mesh.indices[3*tri+0] + v], + mesh.vertices[ 3*mesh.indices[3*tri+1] + v], + mesh.vertices[ 3*mesh.indices[3*tri+2] + v] + }; + } + } + + // Transform all 3 vertices of the triangle + // and check if they are inside our decal box + int insideCount = 0; + for (int i = 0; i < 3; i++) + { + // To splat space + Vector3 v = Vector3Transform(vertices[i], splat); + + if (fabsf(v.x) 0) + { + AddTriangleToMeshBuilder(&mesh_builders[mb_index], vertices); + } + } + } + + // Clipping time! We need to clip against all 6 directions + Vector3 planes[6] = { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 } + }; + for (int face = 0; face < 6; face++) + { + // Swap current model builder (so we read from the one we just wrote to) + mb_index = 1 - mb_index; + + MeshBuilder *inMesh = &mesh_builders[1-mb_index]; + MeshBuilder *outMesh = &mesh_builders[mb_index]; + + // Reset write builder + outMesh->vertexCount = 0; + + float s = 0.5f * decalSize; + + for (int i = 0; i < inMesh->vertexCount; i+=3) + { + Vector3 nV1, nV2, nV3, nV4; + + float d1 = Vector3DotProduct(inMesh->vertices[ i + 0 ], planes[face] ) - s; + float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s; + float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s; + + int v1Out = d1 > 0; + int v2Out = d2 > 0; + int v3Out = d3 > 0; + + // calculate, how many vertices of the face lie outside of the clipping plane + int total = v1Out + v2Out + v3Out; + + switch ( total ) { + case 0: { + // the entire face lies inside of the plane, no clipping needed + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]}); + break; + } + + case 1: { + // one vertex lies outside of the plane, perform clipping + + if (v1Out) { + nV1 = inMesh->vertices[ i + 1 ]; + nV2 = inMesh->vertices[ i + 2 ]; + nV3 = ClipSegment( inMesh->vertices[ i ], nV1, planes[face], s ); + nV4 = ClipSegment( inMesh->vertices[ i ], nV2, planes[face], s ); + } + + if (v2Out) { + nV1 = inMesh->vertices[ i ]; + nV2 = inMesh->vertices[ i + 2 ]; + nV3 = ClipSegment( inMesh->vertices[ i + 1 ], nV1, planes[face], s ); + nV4 = ClipSegment( inMesh->vertices[ i + 1 ], nV2, planes[face], s ); + + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1}); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4}); + break; + } + + if (v3Out) { + nV1 = inMesh->vertices[ i ]; + nV2 = inMesh->vertices[ i + 1 ]; + nV3 = ClipSegment( inMesh->vertices[ i + 2 ], nV1, planes[face], s ); + nV4 = ClipSegment( inMesh->vertices[ i + 2 ], nV2, planes[face], s ); + } + + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2}); + + break; + } + + case 2: { + // two vertices lies outside of the plane, perform clipping + if (!v1Out) { + nV1 = inMesh->vertices[ i ]; + nV2 = ClipSegment( nV1, inMesh->vertices[ i + 1 ], planes[face], s ); + nV3 = ClipSegment( nV1, inMesh->vertices[ i + 2 ], planes[face], s ); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + if (!v2Out) { + nV1 = inMesh->vertices[ i + 1 ]; + nV2 = ClipSegment( nV1, inMesh->vertices[ i + 2 ], planes[face], s ); + nV3 = ClipSegment( nV1, inMesh->vertices[ i ], planes[face], s ); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + if (!v3Out) { + nV1 = inMesh->vertices[ i + 2 ]; + nV2 = ClipSegment( nV1, inMesh->vertices[ i ], planes[face], s ); + nV3 = ClipSegment( nV1, inMesh->vertices[ i + 1 ], planes[face], s ); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + break; + } + + case 3: { + // the entire face lies outside of the plane, so let's discard the corresponding vertices + break; + } + + } + } + } + + // Now we just need to re-transform the vertices + MeshBuilder *theMesh = &mesh_builders[mb_index]; + + // Allocate room for UVs + if (theMesh->vertexCount > 0) + { + theMesh->uvs = (Vector2*)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); + for (int i = 0; i < theMesh->vertexCount; i++) + { + + // Calculate the UVs based on the projected coords + // They are clipped to (-decalSize .. decalSize) and we want them (0..1) + theMesh->uvs[i].x = (theMesh->vertices[i].x / decalSize + .5f); + theMesh->uvs[i].y = (theMesh->vertices[i].y / decalSize + .5f); + + // From splat space to world space + theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], splatInv); + + // Tiny nudge in the normal direction so it renders properly over the mesh + theMesh->vertices[i] = Vector3Add(theMesh->vertices[i], Vector3Scale(collision.normal, decalOffset)); + } + + // Decal model data ready, create it and add it + int decalIndex = decalCount++; + decalModels[decalIndex] = LoadModelFromMesh(BuildMesh(theMesh)); + decalModels[decalIndex].materials[0] = decalMaterial; + } + + } + + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginMode3D(camera); + + // Draw the model at the origin and default scale + if (showModel) + { + DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE); + } + + // Draw the decal models + for (int i = 0; i < decalCount; i++) + { + DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE); + } + + // If we hit the mesh, draw the box for the decal + if (collision.hit) + { + + Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); + Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0}); + + placementCube.transform = MatrixInvert(splat); + DrawModel(placementCube, (Vector3){0}, 1.0f, Fade(WHITE, 0.5f)); + } + + DrawGrid(10, 10.0f); + + EndMode3D(); + + { + float yPos = 10; + float x0 = GetScreenWidth() - 300; + float x1 = x0 + 100; + float x2 = x1 + 100; + + DrawText("Vertices", x1, yPos, 10, LIME); + DrawText("Triangles", x2, yPos, 10, LIME); + yPos += 15; + + int vertexCount = 0; + int triangleCount = 0; + + for (int i = 0; i < model.meshCount; i++) + { + vertexCount += model.meshes[i].vertexCount; + triangleCount += model.meshes[i].triangleCount; + } + + DrawText("Main model", x0, yPos, 10, LIME); + DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); + yPos += 15; + + for (int i = 0; i < decalCount; i++) + { + DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); + + vertexCount += decalModels[i].meshes[0].vertexCount; + triangleCount += decalModels[i].meshes[0].triangleCount; + yPos += 15; + } + + DrawText("TOTAL", x0, yPos, 10, LIME); + DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); + yPos += 15; + } + + DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); + + DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model); + UnloadTexture(modelTexture); + + for (int i = 0; i < decalCount; i++) + { + UnloadModel(decalModels[i]); + } + + UnloadTexture(decalTexture); + + FreeMeshBuilder(&mesh_builders[0]); + FreeMeshBuilder(&mesh_builders[1]); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +// A really simple dynamic array manager +void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]) { + // Reallocate and copy if we need to + if (mb->vertexCapacity <= mb->vertexCount + 3 ) + { + int newVertexCapacity = (1 + (mb->vertexCapacity / 256)) * 256; + Vector3 *newVertices = (Vector3*)MemAlloc(newVertexCapacity * sizeof(Vector3)); + if (mb->vertexCapacity > 0) + { + memcpy(newVertices, mb->vertices, mb->vertexCount * sizeof(Vector3)); + MemFree(mb->vertices); + } + mb->vertices = newVertices; + mb->vertexCapacity = newVertexCapacity; + } + + // Add 3 vertices + int index = mb->vertexCount; + mb->vertexCount += 3; + + for (int i = 0; i < 3; i++) + { + mb->vertices[index+i] = vertices[i]; + } +} + +void FreeMeshBuilder(MeshBuilder *mb) +{ + MemFree(mb->vertices); + + if (mb->uvs) + { + MemFree(mb->uvs); + } + + *mb = (MeshBuilder){ 0 }; +} + +// Construct a Raylib Mesh from our MeshBuilder data +Mesh BuildMesh(MeshBuilder *mb) +{ + Mesh outMesh = { 0 }; + + outMesh.vertexCount = mb->vertexCount; + outMesh.triangleCount = mb->vertexCount / 3; + + outMesh.vertices = MemAlloc(outMesh.vertexCount * 3 * sizeof(float)); + + if (mb->uvs) + { + outMesh.texcoords = MemAlloc(outMesh.vertexCount * 2 * sizeof(float)); + } + + for (int i = 0; i < mb->vertexCount; i++) + { + outMesh.vertices[3*i+0] = mb->vertices[i].x; + outMesh.vertices[3*i+1] = mb->vertices[i].y; + outMesh.vertices[3*i+2] = mb->vertices[i].z; + if (mb->uvs) + { + outMesh.texcoords[2*i+0] = mb->uvs[i].x; + outMesh.texcoords[2*i+1] = mb->uvs[i].y; + } + } + + UploadMesh(&outMesh, false); + + return outMesh; +} + +Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) +{ + float d0 = Vector3DotProduct(v0, p) - s; + float d1 = Vector3DotProduct(v1, p) - s; + + float s0 = d0 / ( d0 - d1 ); + + Vector3 position = Vector3Lerp(v0, v1, s0); + + return position; +} \ No newline at end of file diff --git a/examples/models/models_decals.png b/examples/models/models_decals.png new file mode 100644 index 0000000000000000000000000000000000000000..48e027fe2d1711237f457995d46ddcc0647a102e GIT binary patch literal 62387 zcmeAS@N?(olHy`uVBq!ia0y~yU{+vYU_8XZ#=yWJp1k%11H zGcDNj>&wgFf`2SeeKRvN+YU|;pKn)pW-$Q6;bCaCG;<=MAPD(IgSs~7}!H@lnOTcpH*w|W= z4tJ2-+?*3!+7BG<7MHwp_pW>J!3++bUjhz!;)}OWoOt`r3Auw;GaI)acFc-wE537> ziOX#v1G-|@_hdRoZ|303b*Kmk6o;|gs@_NQeLn)>eiUtwWBYKYs*E&6T z+kZcyyTvlXy}8DO#m%|FfurYKU60ztiE>Oji#-|2IePToOZmz!R&20maho2|yG$T} zqrpl(eE(l2_BOK#GH+XYmUUkgI3UNgc(eRs&14f61x15fjEcspAdP38lr34@(yiSt z+ZS;hu##6W6sX=J++59^?^|b#A`M zV%p@K01CmM{cQ|NEN<2c%?74Dd42L{7ct8+E%sjHc3EMefWy7-j6tW59Xqxm@h}@( zeSLk~{r!s4mmKE`L?*DiPMn@>;@}RB+81w*XRt}|GF}moc-z2pP{eSTWu1xiWhF@9 zX(u@|?ETDmX?xO9F1Fy{;I`uD=L{{Ztc>36^G z(1-W`>)XWT?fTU;wg?=!_A?_VCuPIdt*oo3OqkG6?)2{7-tJ4B6Cb3cK1fNF+nBg& z$r__s^V||Rdg81sX1#HDW-w-POLuUKSS1mA&oqjs!6~7nQ#8#gV6sT!2lMMG0uP?0 z7=%wwt>Ao96I1h{>EXNXavuNtbu8r`ZdI>-{(G*^{HZg1!3Pdb&cqX^PC0Q(`T6;^ z39I`xxpT*@6jxXKhQIjA%-iL?it*PM zpVmE$*6G*Vcu02p86O`W#%EDHf9`bb<$A=lhbND156}6Ax&6Z1=NZh|`MV`ig*o8) z<1gx0gx5PPU*J36PBwi*gH+tYg$sGu`D7YaGtM*&vR1sbX%o-lgp^i>wdwXBOy{^? zmdfH#XcyI-+i=lfnXi}BTt>;W3tid|y!f19z|8guzK=slRE!}h>P zM>DamO~Jd4jW<)UZL9h^qniI;t6io^y_n0-$jI3C^z?LLp6;uw!;P0LSz?fLXNTar zGL>>Cx7BkdiZcE9R+k_h!D?Do*xBsFr`B$BqRXG(vaIKdNtgbb4AEoCmUSNQ8YbKl zKC*P)6-nNRHihl#ULNv#-+R8*bn17xy|n2?y9z;N-v zOu@GM_L36+{w80TB%Chr=xNf8nqO>(o3FobteyN{dD*;UW!H~yN$rOe}$61J2rZ`))*dK$deOVhzWzVoZy}c3vGSjvpJ$(6;o9}Qy1H8O$B!Qp z%Y0@sT{oNbj!SYcYi&yCwgpSWzw$FntdTI1-1kbpxmvFFCI8OmjZ0e8^sFx&b!U(H z*sitqQPz@U=QG$_5=D601SIat_{Zt==xtnN^Yzn41H(U!l7|nr-ul_lY0T)K$CUWs zOh*d~d$YPZKeITy_2HG#{cWY{EVnzu-@bjzV`pcV!dg>XYs)MyF76y2E*|s$MQiKg z(hCK=j2GUx&#aSVUURwe-cN>~v*mj0a>^ETUtFwgBJ)V{x(~Z*o%G6&#O2 zi(|VnY2!hW_{DSiZXG#x+W5G{ytSTZwju-sDncenRJdbI6 z=O1aao6^zGm5q!hC0<(M8S?q@p32V>r%s;^JR^Os+G&;8`jic&1t}7&hwWJ$jB6I$ zGgKCzt4SmczS!{)OLsCZ{vP{<38%YVD{OSH-9on&YLoYC9ZGk z?AhGgvr8n`OUv>)RM{@$l%hbRVieFnPnXeEU-${=8*x%eSxRy{*$*cW2$QWom)P-%b)% z5EK-A@HApUa#iB5_H6Z(FJfON268t|ixaf^nYG2%z{n|~B$a2XwZdY_bQ2c0AdU;4 z-%Y+4yoSvn)lm3dg8^gzlfA#+T;1UJ@5S-AP1Dqy`fjJDr7fGe|L@_BS*mFcfvEiE~wR9P%Y}P-Min7Yp-)d z;SqMrZI8>Q>&2c@P*!&SyrHnPH1)=YL}q6P2ZlTA9-4s@)ra#*KlEf}bT5OOG6CR< zX_k_kbAy{=!~1u_7jlko&AxuXOgX=aJ$FL=pC5*879I&3^7`a`9h~i1Hso5(H_aAn z-nrBAu1$Jw?%561-}Bf4(pl18zL+=R;vLfvCkC_MhEmCk6%C}Aj@bJaO#XJknah&;d(eFe? zq>YFZxD7D3uZb=!%5As#pUyP_AObdrF*R4{mgqsCHlNAFi> z_yXy3&(F`d*Vy#y_V)aPa|Hx=i!TK1RcE=vcv44aN#%}5yV4sj{AK>KZ+^mto$Z%8 z81McL3=3;Z?e!zvrSczQrW zuUXDXf4?W^>K2%%IqEsQZ&BFI6@9p3%R4n)mJ8NpJ1*I7+abxD{R-TEGYRc&V_;P@ z2+`+~iM{6n_&R zypzz$ttVV!o5yjL7<%)cTV&CZ@8zV2dj(9w3Un+`87ImRS(vWY_*mfvajp0U0B+Byib;Scd16H z6Wb%PlAPX^2X8b;t?IS9@aFj8c7Dk}fBqCaldX}pOPcmmAWNV>?B0}C22Jm^AC5lF zu$dsvv{-h+#VN*8OchQEEA%!>t?)Qn{+;uL?~Oh&woYYveV*5I8jidy{mwbRPxbI} z?c#HPut6Ou5V9b1^*mT$rESV-X2+PntkoU z*LD0}fA<$Yc5CbC;Aq=h{k^GIYA&aut&3-7$wlS8d{^DfGG2-#**`{f7vPTcN~mzcNr z?}-mGJ7QkjGe3zFRC7~f3lmFgyI=n=;BSj=&fI=g?`Z}%Zr|qL`DcI9QLeTbGbGpo zm<68vSa^X`(r5dE%T>o3uc*53n0Bz?2z&N(7I5cd{+mC}J~k6}xnyiHQrBfU5i4gd zb?yph!n9QV6cYycj`S}O=Sno>lCj}&bd-86VtH}9=3DQ;T z?Q7WHOEc=;{q^auIy1-p%3obs<-HGfJ*`pDlUkC-)!pBpeq&p%^c|1LuxF0D4Qqct z4qyEAjR6z^$>l$i|Z~c_WwdrkRNL4i0#gc8p+IvDkV(wdsx{H1%Kj}>i*O!oBH}G&!PoKM^ zOnguJlf&2ZOV{RTZ=PnkBin^jK0tw9%)?l=3U0( zOcRzB!jP0@lH`=|MP&8Fxi>zR2E4P|dGN!_tF{RY7xzmu&H8Ck@R04W=!2teSGp8) zjOBfOeR(=NI}hs#o|$FZ-PqdNn)vnA)en9g_xtbj9FkeHcM)25{v7#k-Cgomd~#Acb!`j)78VDSpR z)F!i*|I4!v+^PCB>EX4<(?d23M?YV@Xi<}*v2pPYw;x+FFCUmIFoS((1e^a=xAV~# z+>1?eof%Ai8}9m&Wiqw5jiJ;jp@c2PM3winfJAJP>8uT!+>8i_>s{=sVV zvrEdbZSCiY^XH!rh>5XTBkbbs&3#xtLn5nqqhSG)zp(UK#>I*bXCXDY|6)alyP#fW z&$1PX!r-2%u<=)ChAV;#bJbgB&a_(m^@f#vXlN);YisLatHeDOADa>%9qCN4Z}K}N z6%Oe`6MfU2gm-4-Fg`4qKnNvmM_T|B^ z!gA*JZ`)?pcIC>I#Q6df@(ZUwkg54?$M#6<%f&nXcOlLST&(Eu7vii{ijoj#>D4+n zl+6{8G<0Ok<11@hZ(ld*scOz#{tG=0At6^b_^V8vI+f@Df9GkZd-e7vB^)T*D797p zvvP@}!X_Il=_v~Bx6VFaaE^WFX89eDnAPk;@*Cw>v2ri`;qdKx#+?gx)7-5U7Qfx0 z2n_`7wN4H0UVR*kGcR*KOi51Oa4|IXM(H!HJ%+w3?R$HB+iR0{R)5z!Jjb&5z(1KY z-s@k~a$8j$?wn`dby%w61h4IkzY67v*$jNGEnK@wCd8C09cM2(p1h*%XnI*viukF~v+XyO&xumZ^h7%h3)(I^5_pHRt&5f;^xwNf6e!p={^@pB^!XKQRg8uN_ z`n-VmO2OCL`a8^|rKQ_=rOgZ?qNDk5v!o;@GJc<}q<=iaO;LbpN#DOmLH*~YBGj3$ zEm)lXyj_fw!Q}VH4-cK$?Ctko{9-D_v{=#MDL91HRysmM_}K$K#wUxbR&MsZdp2aY zV{qK0huX3Dj+2lZ7`U7iQrQ%p=rND&Z!k}UA>Ib)e!o$;UF-{(Jk zzrWsrXW{?9t{WU5)i?ZkZ(na%^Y2^p!;`!Hc_#P8H|~}!;e2>{y1t}?`zN8-6Muew zZaiiB^ycXWYvcFV1*m$Yr>F0zcI&^Rs+;AJTQl)iMO$gq1Z#cgQb{q>GTz}V2RVB==tRP!aupQby? z-;gv6nV9MkvqyH_`u+RoGhX3rygR+|JZQME*;;==@QRKY!v*X&E`~elcdcP%O zRBiYDIcUK3LW-#;et+Fxd#PuO6&?BoB;J500$gyKaGL}Uxjy^s)2NrEuv!;j9#F)A0Ktg;KEBBIBN3|t$WM$lq{|Rt6 zu3M+a7EmSKy8|3{w^|u4XFTX@W6*VGxbl+W;cWAKqlRgbjnl$2GcyfWtX^&06DMXd z>l<4&$A-H92R^jAPkH#`>TaI&JiCM+fBvfT&gGHfb~-*KQapL-`3Z@u`OQ<#&$F%g zUTR@w)%5x4zrVi^&gGxrR$N^CAuUE*Tf6Q4{(63oDY`K`1n&K0uuLdAK{E2s$uS*;bGA5 z?z%&K-qIB-P89t9mfQB|Q4-q)BaHy}*0_(=zrJL)O`0UMqjd4|xZY{HTX-0Y^krpw zr-Fm&62w(q3!^xC%BpynxJRmD*%*)DV_+Z(` zgKz#{{yv|{TJd+l9FA8l8rs^EpX8XEo3|}lq5^7n&8imP;UZxt%)DvMotrZr{`e{F ztTywkW!bdGd*Xt9)102PGh}>YUNZaAXU!>qp&Z)pPqc0Gf9Chs6^`lq$L&v!sC~e5 zc+uSBl6f{&eqUIdzVNB%%oVuc+PWb6a^cR@v$ITj%HQ2d%*f78W_WwQ>i<96!;4(I zC2rlmExE7ux0|tkL*D#*ZS2Qb@A3k#?r^NYZhLqGd#RCV=I!}>*Z(DnI!`~yKZQ2K(`ZXH{IJke!>fkmu zsfb))p>JwBHSyV*nGthkgoF+;yjpT*hGBE!=VxbmX3d(#v*7X;2lvlSpX^_>=w$sC zEh#_w@$vD8$JU+XkP$g}^8C?*3TI9qJ#gxb&y?zf?=prxO`v&d zrWQptwYC)d`L@;57Oq&qv5x=BPX=A-X3jko-wPcMU5xXdc+k^-X5&;=qtA-kXU-pB z+asLz`)9Pp-N)e}obzPcG#RF@oNr&>w%YyuoCcKyS&@L}EJxH!Ew#6KzxUYtcTNC< z@U9qv>#i+d3ZyMNnV}7Z3zO`#)b(QO-1rYKtV&cqEWrHZ5%XQ`E9cC47BeV=<}?;} zHZksOY61n#kmV5Tq|3CNO z;X}sj?e~5%c>ekKdHOrgK&cxy3(SL@H%^zl@pD7S^kj>w$BKv5mEN~8ma0v#7MV0@ z63>ZL{SMyO3mQ%(3drAo!|5Rx&Ca^_q09MWx@#KS?_6lU*?%^crSf|*a&)auQ_^P^+X+yC5}IS6A2NXSBaR|2n>s zN1~t3u=_MkJh%J8Oo^Eiljizv*fpQ^Mx}A^)YKcyJn1=HB|N+xefbgYOm52MehzI9 zX4^8JRMvlA_3w`*^R}n4&{kvc0ymkW_Vf+?Zw{Ny>z`M16f_0e@D5xQE$qxI>Aaee zX$+e1JFs}cxeqUmK6peenLN!&wpa35o~=`0z+XnWv(;Zd$+F2lING|VWESgA?m3k^ zYuEg$~=I9u@bw*H3t{JXo3E?Bha5W_7VJuNLRG3HW>sOac}-fQ$? zcd^{-;ailOlOthbVsc=*bd%YdW)XRtiV2G5=F=Is)Tdlp;#qOnz{F(A!^7+@>ii{- zM9p~XU(}o_oUxUUnO*u_)+M*#c@KY_b?1q%|Fl*&FpT6I0Xwz0bw?Y4m`{U++8|`l~CQ4W` zL@!S+=@dPz0iKLwh_&N;+oIv=D0T16nl(I^7BTV2@2^R(`2CXmq$1la*Gl#`JRO%` zZaOsmz+R#G`~M~|>Yv_gc&7A(k1OLFODfw_J7(q#OWnh) zY;04V4{E$)nVZ2O#Bg@j0hNT!>RU1<@GdL;`eoMN1KYNwZ_sm3mSAKEmy(HXa{Yfo z{%r%#XCCuiN4gS4dfFIXDl)unY4D5fD&C$_@$H#%v)Bg1U%VEVcwetZ2@> zW^lW@xl~dt@f$KmPgdEE8yr&e&-B))oYe@A+Wqjx)760_+}#fG)QLXwgv zFWkS+Z+Dlgr1{s&%gZJG=GmNFuwcP~fY8vR4AO5H=C-l!(%rjZ!-T}+eXCbWI;eu-WuI}!QznHgF%5F*V zc6Vp5S$~$^6E9yO*zCB}vTvn;^luSkYhscntlB@B>hr zP$&gF%42iM!f&P1E#aoKYMhF7Z1vL2Y__SAZKdt!67MP>V&B8wGJA4wUf@y<#X|?! z_iUYgDK&nQy7w$4-{=8bBz%NoEb*-LF zjm_=B$K5;&Ry#PnW4QPA5W}+n#w!^7Eq8x@^tR)4*OWQ;Sfg&Sav6BNw^KB|@Y3?P zVU$^a+kp&@2Yihe`A!J<$}Zk4yZC063Cjx!CKfA2h3OhzT?R{j+%VF)Up(od;fG~~ z7lL#rSY*g|GHqx)#r;M=py=bv-~N&*jj~cV&fb6WD}ZOmP1!9aZ_Xaq=Q;9*Rq(;X zBmu^IW_(4;+#4qT72k24>Be1|yJ(gg`7D~yxYtvs@UZO5AI=dmX?XoA3CC zCaWHq1DDrI+_)k6ub%nc>z}<_wm<)F-}XPg&dA_XbKW-gvpo#4Cr%wxP(9NAsQ!ZP zi^Y|q^&A18-w99fz46Y@v79kO*j5+R|N0E>e?0=vf1L884YU{-C-c&dXYHf$!&& z_sn<}SbON*t31PCbx7<=gZPuDX&WvCB?U|tO@Ht#A^ibMnU#aAkkdk)L+4KiXzQPR zz+|$zLMNl~{Ip%BnfM*~dTQ*Z%s(-g+yaMvjk6 z*5W#AczAqtczR@dc>d39knNpcFCp>IG2O;tu7JY)iLzm}Mn(n2#fCjhui6+?%jYLV z-~0OLD0kb%oBbC-Un?3-j(2ruG`x#W809*5Jyl(nl5F&tVT*=v8mmU}^) zO-2~omMdH)xBRm-qF0?TYOvxrFmLXAv~|mtl!%>0s?6&impPU-d}}}O=1}QnOS|n2 z=a?28H{A2<0JpMa#KO7W4|1RPIQ*H<91&Xg>*RqC?7P@mcUaDElwJ8N#r5ue=To{b z7XO^HM?j&pQat1Sq>UR5nKRt@em<+1@b<`=c|FH2gJUJX!BVFd^a&QJv!ujTR9HCs`|~^3)Y!CrT)K2A&-L~3?cI}&cYpqD zUOO#e<_hhE9rFb%x+Iwk-XH(pe_v9<;q|4u#rbXQ=b9L%Z>U}RI97jgD(gD|hxmJ} zw|+B5iE&s}@-FGVaQ5S3*(n#Vm`X8i;RlsU49hoNR1I5vv&Mvl&7Gs5`|cd0-k2`-m_->&N*?e;Foj9mwHc^a5z2d&)>fX-5Q^)yveyR z%_I4B%akco3>y6QuUfmdHF|5=+bFgRX(cllRy=mJ$IAvbkv*pA6hRl;>Y-S$ucTlN+ugkH5XUds;zLlk?cw zvuAlWxcy0Z-_l^^aYA;b=VY};YsJm!=hGNW?-&^wJ@}_mdY`?B;Vq_v-$kTMSo9LpO=thG@o-i@%HDB^1k95oS9zL959>R zoZ|Rf{mYjx54aqA%P!=ccy)F4!KCVS_fi)eI~lQsqxOQ(M&+j)c}~>b+K|Z1{9;Dj zg~B}s)|xMC8qOp%%hq}yR!Lc*)qcIiEzOOsqQq#?H=W9fe5wIKVUinK`tGezzmm9M znR6nqI!@>zE!jZI(!y5FrDq?MM=5dB=ADE3l^>m^fxla?o!d!J_>&2 z7r!wb){tle)mRGymw-zweK+TXiq-}V{eO$Y&flp&_u=n#dA7U<8@KJK;j_yt|7y3x zVIre=$VAu;!K-PyGpws{%5~YFEQoEm#@-ig{RD5 z&|fBdU}-$h0_h7EQ~og@m3;U}pnr!%ra=yq-rC92rlv~tFjP(v-`U)l`(?VAvDghO z(=9y94_3UR@~@6C z*w33@_<_~DN}c6N9H*TeTigFBJEu;Z*!gcB>pRPz|3B+9E6cMV$_tpm{P)m_4#^+C z4k&k(8m(r_l~Y*C?9hFVX&s+{E)$R0Z^H;>=IDrk-|vJc+;>m+4+v&h*T-smS?#a} zL;HaY_Lf5};I)IIXR&uCokZ^$V9f5Gj8GYjXs zv_9htX3b=qAnnMv>{zUtLb1d4U6+lP7H-&-B=P_MY5hB4hYmA6tn@PrYtwJGu%2MG z$~$W@&wV+8D)!R_drBr;+3oL;*q2*u<5BbFop4*A!2wX3P&8%&tz~_7_o9GAq@u%_ zzmoj-YmRV;d~j{{IK6Jl)TyB6m2=R8lc!G`=iJ*f^WgRC;%oS?a7Ip+JJImHPe3SL z#$o%C{XhTAefaQpKTmo5-t-@T9*bAlb1z{)FIVoCs0+%Aq+9R`L%@9qYye$2?d zB7Xn>3nm9G8K?UvMl|U1aJH;o+x)m8ji<)jv*4tlHs5E7b$ewO@NsXFv6>ynXnZ5x z-r=FcTS>Jbv*XQg-0h+yj>v14&z~^sn)~a@TdfR_udk2)-_K@HsAzEOrG&5MVnu^J z&JW)0az9Xgn+O<}{&}q;LP%A29gA_wtKDSHa<@|Mvep#jvYnQlNxNTU4#rPc@?s=}3c~ zrbceY3rm|9RHvUhb;@mV;|T!=`zVPeyg$FJySUrmZL*LqXqL34BcQd^#=*ICHcAqKxqdMTV#-yfIHGiu0_Qoq)?-o8HhM%72Y z=1nsg&YffV^oIRR%o9G&Q<-rrI{z5&i2Q#q|JF(&Pc3Rk?17#w_gSs951nY-nOIx$ zExBNd?BdPxU;5cW$#`1XLjCtlYjqlTN|jkYe(^H)@P0kHw+#%BE1&~4jTZ$JlvpZm z+>}_bd_&TTX-}RfUYH`3=y1P;Z&$0Oo?hRpht}oqV%YTc_1i8l_n&;1Gm&jxUg?u( z%5Cpcaz51Y?D_fEroeOBa=CBO`!A;3UtnfX^FNarxga%Zjm{Yp@5RSnecEw0&3%s6jSJ*Bd2anSoYlx?#^SJ9UP1iD>(~8mM-{jlFP{Cl_@rPsN6!tu6QEX#k0E%R z*^gs|H&?Pw_@kuc#0>${k{&!xNslP~#C0d)!o{6;@7^`xevx~7o1ui1l#xy4Czd;$ zjCWo9PQ`Iw@C@G`zfb*i?fypbkFjj;BoAI=be#8h!63}>&%*j7zpEP4I=-QC@R zZ=C0gGI}oh-6(0X`^dp#UXu%0-ri13J{T)%RCM6UKVyR)xtm5A+`Jbqt-g4(e_{Bt z{(H4XMXw(UUS*VwO)|ap06a#rz=Y-09vulW2J>n5401bvzj&+8c441Dal-S%uF--O zO;@;oi@=H^Y;Aq zxiIbAIlm23+1c4_0&IoTbfb?MX2@TTdGa*Q z=fYn(1H-a2GiO|U8qOTO?m*vN*|~ou>Yo07aaWz^uvkwAC}g$U0u8_+yHwx-o8IBB z&DT;HN*(t7|8-d5*zuzZss~ONeEi7G_Jr+AE4TOyv1j`6`%(l%MOkmVd#OL+-w=3~ zFXq;l&*$Se-TB3Q{E}{jMT6ObtgNi08M30HM;Q*yx36bA-{mvYsP*A<|0}`kE=Hn1sxrqEngR?=_$8f{QBS^ zGiV}ogXWPkCkJt^O`DlkH_Gonu}L=iIBVt4P+m*k5D|X^!ysp|}Q2Rqq$z^}!T&cX~vvnPvorXMS4Bh-USbJZ*JFI@rfJ=jq z@yku&sm=#^USxjgyBoze!D3hHbDn3-tqIak+|7>%+dJ~D21U&3i$d9;BCp|-fWlhq zhJ7#hEL+xg@Z7mRm2`t3#alae?v(74w?D^ltC-QKZ-!rohQ2s6Kf5&ZixBOiISMEH zEwvl(BywEF4@1?KX2T9 zLY61zBNKP^7dOMh8VjO1JiNS`-a7R&XJ%$@u*jGuc7)-s4F4kgx<4FZ@|xzyFB>Vf zxw5B#TIiXOH5GRS6!r--?cxzg+uq;L?_5{+ufesgtBdRKuF}^MO-%~htAt;*6fma? zJ!veTZo@b)gY{O3->Sn~mjtHsPe`{fDk?g`*M8!J2b)0M-(RLXl#Pm?`K(EcZ7p+= zXfRo0e2CR%VVCgn&d50jo)$OR#PC#|GU7>->f(7J?(U@1_^vb2ZBEJ8|CjkUh$yRP zv8QOf{d>UF+G&-=K95$@9f`e`QRQ|Co8=cTy`RAmV9nz8-fm&-EU8Vh6F?n2)^nit zH$$#-LxDQW&V#zj%7+c=|NUX?7m1FJX1g$tD}tRNUY+F%!}W=RsSI};{yjTgKIv|r zLi?^atd-xG%c8AS8JTWfzjW!+A%;WY>tYfk_Se}SZsV1fkh867Nz~b6%ry1l^T!E4 zK0lXlR?$~4nASemaYldp!GO?d2OV7b`X?9UocPZyk}mtp{rw}UOn3RY?5qO&1gnc4 zi$tflPx@jwMNf9gw)^hh^`D#?qCOf_edm0tS>RFX0BU%NS%RzhW>uC8-)kHE7E9^m zar5)1GsK46xOR=LOlY59$Hpd=!z-)LOWdpd>v*X%qDzU1=hP#o0)6H3V=^)_E96A1 ztgLtxVxptD&8n}ji+#YynQ@H0gh^sotN6mrVhj2_dp24%_f0ZsZV|ATD^Gl1^XETP z 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

AIX)i);+Q2;^({W#g{?F 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 II;Vst0D_a9V*mgE literal 0 HcmV?d00001 diff --git a/examples/models/resources/raylib_logo.png b/examples/models/resources/raylib_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..15bbaa2f42d01ac30fb672d31ab00701e6c32895 GIT binary patch literal 3672 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 literal 0 HcmV?d00001 From 79fd6be0084a80dcbf7c7af2c1ccb12b78b77c47 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 25 Oct 2025 11:14:53 +0200 Subject: [PATCH 067/102] Minor format tweaks --- src/external/rlsw.h | 73 ++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 626cb2cc5..bc7a813d3 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -791,8 +791,7 @@ typedef struct { } sw_vertex_t; typedef struct { - - uint8_t* pixels; // Texture pixels (RGBA32) + uint8_t *pixels; // Texture pixels (RGBA32) int width, height; // Dimensions of the texture int wMinus1, hMinus1; // Dimensions minus one @@ -805,7 +804,6 @@ typedef struct { float tx; // Texel width float ty; // Texel height - } sw_texture_t; typedef struct { @@ -881,7 +879,6 @@ typedef struct { int freeTextureIdCount; uint32_t stateFlags; - } sw_context_t; //---------------------------------------------------------------------------------- @@ -966,11 +963,7 @@ static inline int sw_clampi(int v, int min, int max) return v; } -static inline void sw_lerp_vertex_PTCH( - sw_vertex_t *SW_RESTRICT out, - const sw_vertex_t *SW_RESTRICT a, - const sw_vertex_t *SW_RESTRICT b, - float t) +static inline void sw_lerp_vertex_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float t) { const float tInv = 1.0f - t; @@ -997,11 +990,7 @@ static inline void sw_lerp_vertex_PTCH( out->homogeneous[3] = a->homogeneous[3]*tInv + b->homogeneous[3]*t; } -static inline void sw_get_vertex_grad_PTCH( - sw_vertex_t *SW_RESTRICT out, - const sw_vertex_t *SW_RESTRICT a, - const sw_vertex_t *SW_RESTRICT b, - float scale) +static inline void sw_get_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT a, const sw_vertex_t *SW_RESTRICT b, float scale) { // Calculate gradients for Position out->position[0] = (b->position[0] - a->position[0])*scale; @@ -1026,9 +1015,7 @@ static inline void sw_get_vertex_grad_PTCH( out->homogeneous[3] = (b->homogeneous[3] - a->homogeneous[3])*scale; } -static inline void sw_add_vertex_grad_PTCH( - sw_vertex_t *SW_RESTRICT out, - const sw_vertex_t *SW_RESTRICT gradients) +static inline void sw_add_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const sw_vertex_t *SW_RESTRICT gradients) { // Add gradients to Position out->position[0] += gradients->position[0]; @@ -1065,7 +1052,6 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) uint8x8_t narrow8 = vmovn_u16(vcombine_u16(narrow16, narrow16)); vst1_lane_u32((uint32_t*)dst, vreinterpret_u32_u8(narrow8), 0); - #elif defined(SW_HAS_SSE41) __m128 values = _mm_loadu_ps(src); __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); @@ -1075,7 +1061,6 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) clamped = _mm_packus_epi32(clamped, clamped); clamped = _mm_packus_epi16(clamped, clamped); *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); - #elif defined(SW_HAS_SSE2) __m128 values = _mm_loadu_ps(src); __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); @@ -1085,7 +1070,6 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) clamped = _mm_packs_epi32(clamped, clamped); clamped = _mm_packus_epi16(clamped, clamped); *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); - #else for (int i = 0; i < 4; i++) { @@ -1110,14 +1094,12 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) float32x4_t floats = vcvtq_f32_u32(ints); floats = vmulq_n_f32(floats, 1.0f/255.0f); vst1q_f32(dst, floats); - #elif defined(SW_HAS_SSE41) __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); __m128i ints = _mm_cvtepu8_epi32(bytes); __m128 floats = _mm_cvtepi32_ps(ints); floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); _mm_storeu_ps(dst, floats); - #elif defined(SW_HAS_SSE2) __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128()); @@ -1125,7 +1107,6 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) __m128 floats = _mm_cvtepi32_ps(ints); floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); _mm_storeu_ps(dst, floats); - #else dst[0] = (float)src[0]/255.0f; dst[1] = (float)src[1]/255.0f; @@ -1188,7 +1169,7 @@ static inline sw_half_t sw_half_from_float(float i) } // Framebuffer management functions - +//------------------------------------------------------------------------------------------- static inline bool sw_framebuffer_load(int w, int h) { int size = w*h; @@ -1731,9 +1712,10 @@ DEFINE_FRAMEBUFFER_BLIT_BEGIN(R8G8B8A8, uint8_t) dst += 4; } DEFINE_FRAMEBUFFER_BLIT_END() +//------------------------------------------------------------------------------------------- // Pixel format management functions - +//------------------------------------------------------------------------------------------- static inline int sw_get_pixel_format(SWformat format, SWtype type) { int channels = 0; @@ -1920,9 +1902,10 @@ static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t off } } } +//------------------------------------------------------------------------------------------- // Texture sampling functionality - +//------------------------------------------------------------------------------------------- static inline void sw_texture_fetch(float* color, const sw_texture_t* tex, int x, int y) { sw_float_from_unorm8_simd(color, &tex->pixels[4*(y*tex->width + x)]); @@ -2016,9 +1999,10 @@ static inline void sw_texture_sample(float *color, const sw_texture_t *tex, floa default: break; } } +//------------------------------------------------------------------------------------------- -// Color Blending functionality - +// Color blending functionality +//------------------------------------------------------------------------------------------- static inline void sw_factor_zero(float *SW_RESTRICT factor, const float *SW_RESTRICT src, const float *SW_RESTRICT dst) { factor[0] = factor[1] = factor[2] = factor[3] = 0.0f; @@ -2091,17 +2075,19 @@ static inline void sw_blend_colors(float *SW_RESTRICT dst/*[4]*/, const float *S dst[2] = srcFactor[2]*src[2] + dstFactor[2]*dst[2]; dst[3] = srcFactor[3]*src[3] + dstFactor[3]*dst[3]; } +//------------------------------------------------------------------------------------------- // Projection helper functions - +//------------------------------------------------------------------------------------------- static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4]) { screen[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalfSize[0]; screen[1] = RLSW.vpCenter[1] - ndc[1]*RLSW.vpHalfSize[1]; } +//------------------------------------------------------------------------------------------- -// Polygon Clipping management - +// Polygon clipping management +//------------------------------------------------------------------------------------------- #define DEFINE_CLIP_FUNC(name, FUNC_IS_INSIDE, FUNC_COMPUTE_T) \ static inline int sw_clip_##name( \ sw_vertex_t output[SW_MAX_CLIPPED_POLYGON_VERTICES], \ @@ -2133,9 +2119,10 @@ static inline int sw_clip_##name( \ return outputCount; \ } +//------------------------------------------------------------------------------------------- // Frustum cliping functions - +//------------------------------------------------------------------------------------------- #define IS_INSIDE_PLANE_W(h) ((h)[3] >= SW_CLIP_EPSILON) #define IS_INSIDE_PLANE_X_POS(h) ((h)[0] <= (h)[3]) #define IS_INSIDE_PLANE_X_NEG(h) (-(h)[0] <= (h)[3]) @@ -2159,9 +2146,10 @@ DEFINE_CLIP_FUNC(y_pos, IS_INSIDE_PLANE_Y_POS, COMPUTE_T_PLANE_Y_POS) DEFINE_CLIP_FUNC(y_neg, IS_INSIDE_PLANE_Y_NEG, COMPUTE_T_PLANE_Y_NEG) DEFINE_CLIP_FUNC(z_pos, IS_INSIDE_PLANE_Z_POS, COMPUTE_T_PLANE_Z_POS) DEFINE_CLIP_FUNC(z_neg, IS_INSIDE_PLANE_Z_NEG, COMPUTE_T_PLANE_Z_NEG) +//------------------------------------------------------------------------------------------- // Scissor clip functions - +//------------------------------------------------------------------------------------------- #define COMPUTE_T_SCISSOR_X_MIN(hPrev, hCurr) (((RLSW.scClipMin[0])*(hPrev)[3] - (hPrev)[0])/(((hCurr)[0] - (RLSW.scClipMin[0])*(hCurr)[3]) - ((hPrev)[0] - (RLSW.scClipMin[0])*(hPrev)[3]))) #define COMPUTE_T_SCISSOR_X_MAX(hPrev, hCurr) (((RLSW.scClipMax[0])*(hPrev)[3] - (hPrev)[0])/(((hCurr)[0] - (RLSW.scClipMax[0])*(hCurr)[3]) - ((hPrev)[0] - (RLSW.scClipMax[0])*(hPrev)[3]))) #define COMPUTE_T_SCISSOR_Y_MIN(hPrev, hCurr) (((RLSW.scClipMin[1])*(hPrev)[3] - (hPrev)[1])/(((hCurr)[1] - (RLSW.scClipMin[1])*(hCurr)[3]) - ((hPrev)[1] - (RLSW.scClipMin[1])*(hPrev)[3]))) @@ -2176,9 +2164,9 @@ DEFINE_CLIP_FUNC(scissor_x_min, IS_INSIDE_SCISSOR_X_MIN, COMPUTE_T_SCISSOR_X_MIN DEFINE_CLIP_FUNC(scissor_x_max, IS_INSIDE_SCISSOR_X_MAX, COMPUTE_T_SCISSOR_X_MAX) DEFINE_CLIP_FUNC(scissor_y_min, IS_INSIDE_SCISSOR_Y_MIN, COMPUTE_T_SCISSOR_Y_MIN) DEFINE_CLIP_FUNC(scissor_y_max, IS_INSIDE_SCISSOR_Y_MAX, COMPUTE_T_SCISSOR_Y_MAX) +//------------------------------------------------------------------------------------------- -// Main clip function - +// Main polygon clip function static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VERTICES], int *vertexCounter) { static sw_vertex_t tmp[SW_MAX_CLIPPED_POLYGON_VERTICES]; @@ -2218,7 +2206,7 @@ static inline bool sw_polygon_clip(sw_vertex_t polygon[SW_MAX_CLIPPED_POLYGON_VE } // Triangle rendering logic - +//------------------------------------------------------------------------------------------- static inline bool sw_triangle_face_culling(void) { // NOTE: Face culling is done before clipping to avoid unnecessary computations. @@ -2556,9 +2544,10 @@ static inline void sw_triangle_render(void) #undef TRIANGLE_RASTER } +//------------------------------------------------------------------------------------------- // Quad rendering logic - +//------------------------------------------------------------------------------------------- static inline bool sw_quad_face_culling(void) { // NOTE: Face culling is done before clipping to avoid unnecessary computations. @@ -2930,9 +2919,10 @@ static inline void sw_quad_render(void) #undef TRIANGLE_RASTER } +//------------------------------------------------------------------------------------------- // Line rendering logic - +//------------------------------------------------------------------------------------------- static inline bool sw_line_clip_coord(float q, float p, float *t0, float *t1) { if (fabsf(p) < SW_CLIP_EPSILON) @@ -3243,9 +3233,10 @@ static inline void sw_line_render(sw_vertex_t *vertices) else sw_line_raster(&vertices[0], &vertices[1]); } } +//------------------------------------------------------------------------------------------- // Point rendering logic - +//------------------------------------------------------------------------------------------- static inline bool sw_point_clip_and_project(sw_vertex_t *v) { if (v->homogeneous[3] != 1.0f) @@ -3409,9 +3400,10 @@ static inline void sw_point_render(sw_vertex_t *v) else sw_point_raster(v->screen[0], v->screen[1], v->homogeneous[2], v->color); } } +//------------------------------------------------------------------------------------------- // Polygon modes mendering logic - +//------------------------------------------------------------------------------------------- static inline void sw_poly_point_render(void) { for (int i = 0; i < RLSW.vertexCounter; i++) sw_point_render(&RLSW.vertexBuffer[i]); @@ -3546,6 +3538,7 @@ static inline bool sw_is_blend_dst_factor_valid(int blend) return result; } +//------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- // Module Functions Definition From efe62f0e0df426ff64b14edc75dafd934552f1c0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 25 Oct 2025 11:15:30 +0200 Subject: [PATCH 068/102] Formating review to follow raylib code conventions #5298 --- examples/models/models_decals.c | 397 +++++++++++++++----------------- 1 file changed, 181 insertions(+), 216 deletions(-) diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index 81bbd2796..af1ecfc6d 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -2,7 +2,7 @@ * * raylib [models] example - decals * -* Example complexity rating: [★★★☆] 3/4 +* Example complexity rating: [★★★★] 4/4 * * Example originally created with raylib 5.6-dev * @@ -17,15 +17,19 @@ ********************************************************************************************/ #include "raylib.h" + #include "raymath.h" -#include +#include // Required for: memcpy() #undef FLT_MAX #define FLT_MAX 340282346638528859811704183484516925440.0f // Maximum value of a float, from bit pattern 01111111011111111111111111111111 #define MAX_DECALS 256 +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- typedef struct MeshBuilder { int vertexCount; int vertexCapacity; @@ -33,14 +37,14 @@ typedef struct MeshBuilder { Vector2 *uvs; } MeshBuilder; -// Utility functions -void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]); -void FreeMeshBuilder(MeshBuilder *mb); -Mesh BuildMesh(MeshBuilder *mb); - -Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); - -Mesh GenMeshDecal(Mesh inputMesh, Ray ray); +//------------------------------------------------------------------------------------ +// Module Functions Declaration +//------------------------------------------------------------------------------------ +static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]); +static void FreeMeshBuilder(MeshBuilder *mb); +static Mesh BuildMesh(MeshBuilder *mb); +static Mesh GenMeshDecal(Mesh inputMesh, Ray ray); +static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); //------------------------------------------------------------------------------------ // Program main entry point @@ -67,11 +71,10 @@ int main(void) Model model = LoadModel("resources/models/obj/character.obj"); // Apply character skin - Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png"); // Load model texture + Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png"); SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR); - model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture; // Set model diffuse texture + model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture; - BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]); // Get mesh bounding box camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f); @@ -79,14 +82,12 @@ int main(void) camera.position.x *= 0.1f; float modelSize = fminf( - fminf(fabsf(modelBBox.max.x - modelBBox.min.x), - fabsf(modelBBox.max.y - modelBBox.min.y)), - fabsf(modelBBox.max.z - modelBBox.min.z) - ); + fminf(fabsf(modelBBox.max.x - modelBBox.min.x), fabsf(modelBBox.max.y - modelBBox.min.y)), + fabsf(modelBBox.max.z - modelBBox.min.z)); - camera.position = (Vector3){ 0, modelBBox.max.y * 1.2f, modelSize * 3.0f }; + camera.position = (Vector3){ 0.0f, modelBBox.max.y*1.2f, modelSize*3.0f }; - float decalSize = modelSize * .25f; + float decalSize = modelSize*0.25f; float decalOffset = 0.01f; Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize)); @@ -96,7 +97,7 @@ int main(void) decalMaterial.maps[0].color = YELLOW; Image decalImage = LoadImage("resources/raylib_logo.png"); - ImageResizeNN(&decalImage, decalImage.width / 4, decalImage.height / 4); + ImageResizeNN(&decalImage, decalImage.width/4, decalImage.height/4); Texture decalTexture = LoadTextureFromImage(decalImage); UnloadImage(decalImage); @@ -106,28 +107,23 @@ int main(void) // We're going to use these to build up our decal meshes // They'll resize automatically as we go, we'll free them at the end - MeshBuilder mesh_builders[2] = { {0}, {0} }; + MeshBuilder meshBuilders[2] = { 0 }; bool showModel = true; - Model decalModels[MAX_DECALS] = {0}; + Model decalModels[MAX_DECALS] = { 0 }; int decalCount = 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 { // Update //---------------------------------------------------------------------------------- - - if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) { - UpdateCamera(&camera, CAMERA_THIRD_PERSON); - } - - if (IsKeyPressed(KEY_SPACE)) { - showModel = !showModel; - } + if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON); + + if (IsKeyPressed(KEY_SPACE)) showModel = !showModel; // Display information about closest hit RayCollision collision = { 0 }; @@ -140,7 +136,7 @@ int main(void) // Check ray collision against bounding box first, before trying the full ray-mesh test RayCollision boxHitInfo = GetRayCollisionBox(ray, modelBBox); - if ((boxHitInfo.hit) && decalCount < MAX_DECALS) + if ((boxHitInfo.hit) && (decalCount < MAX_DECALS)) { // Check ray collision against model meshes RayCollision meshHitInfo = { 0 }; @@ -153,52 +149,47 @@ int main(void) if (meshHitInfo.hit) { // Save the closest hit mesh - if ((!collision.hit) || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo; + if (!collision.hit || (collision.distance > meshHitInfo.distance)) collision = meshHitInfo; } } - if (meshHitInfo.hit) - { - collision = meshHitInfo; - } + if (meshHitInfo.hit) collision = meshHitInfo; } - // -------------- - - if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && decalCount < MAX_DECALS) + // Add decal to mesh on hit point + if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS)) { - // Create the transformation to project the decal Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); - Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0}); + Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){ 0.0f, 1.0f, 0.0f }); // Spin the placement around a bit - splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD * ((float)GetRandomValue(-180, 180)))); - + splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*((float)GetRandomValue(-180, 180)))); Matrix splatInv = MatrixInvert(splat); // Reset the mesh builders - mesh_builders[0].vertexCount = 0; - mesh_builders[1].vertexCount = 0; + meshBuilders[0].vertexCount = 0; + meshBuilders[1].vertexCount = 0; // We'll be flip-flopping between the two mesh builders // Reading from one and writing to the other, then swapping - int mb_index = 0; + int mbIndex = 0; - // First pass, just get any triangle inside the bounding box - // (for each mesh of the model) - for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++) { + // First pass, just get any triangle inside the bounding box (for each mesh of the model) + for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++) + { Mesh mesh = model.meshes[meshIndex]; for (int tri = 0; tri < mesh.triangleCount; tri++) { - Vector3 vertices[3]; + Vector3 vertices[3] = { 0 }; // The way we calculate the vertices of the mesh triangle // depend on whether the mesh vertices are indexed or not if (mesh.indices == 0) { - for (int v = 0; v < 3; v++) { - vertices[v] = (Vector3) { + for (int v = 0; v < 3; v++) + { + vertices[v] = (Vector3){ mesh.vertices[3*3*tri + 3*v + 0], mesh.vertices[3*3*tri + 3*v + 1], mesh.vertices[3*3*tri + 3*v + 2] @@ -209,7 +200,7 @@ int main(void) { for (int v = 0; v < 3; v++) { - vertices[v] = (Vector3) { + vertices[v] = (Vector3){ mesh.vertices[ 3*mesh.indices[3*tri+0] + v], mesh.vertices[ 3*mesh.indices[3*tri+1] + v], mesh.vertices[ 3*mesh.indices[3*tri+2] + v] @@ -225,19 +216,14 @@ int main(void) // To splat space Vector3 v = Vector3Transform(vertices[i], splat); - if (fabsf(v.x) 0) - { - AddTriangleToMeshBuilder(&mesh_builders[mb_index], vertices); - } + if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices); } } @@ -250,20 +236,21 @@ int main(void) { 0, 0, 1 }, { 0, 0, -1 } }; + for (int face = 0; face < 6; face++) { // Swap current model builder (so we read from the one we just wrote to) - mb_index = 1 - mb_index; + mbIndex = 1 - mbIndex; - MeshBuilder *inMesh = &mesh_builders[1-mb_index]; - MeshBuilder *outMesh = &mesh_builders[mb_index]; + MeshBuilder *inMesh = &meshBuilders[1 - mbIndex]; + MeshBuilder *outMesh = &meshBuilders[mbIndex]; // Reset write builder outMesh->vertexCount = 0; - float s = 0.5f * decalSize; + float s = 0.5f*decalSize; - for (int i = 0; i < inMesh->vertexCount; i+=3) + for (int i = 0; i < inMesh->vertexCount; i += 3) { Vector3 nV1, nV2, nV3, nV4; @@ -271,100 +258,101 @@ int main(void) float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s; float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s; - int v1Out = d1 > 0; - int v2Out = d2 > 0; - int v3Out = d3 > 0; + int v1Out = (d1 > 0); + int v2Out = (d2 > 0); + int v3Out = (d3 > 0); - // calculate, how many vertices of the face lie outside of the clipping plane + // Calculate, how many vertices of the face lie outside of the clipping plane int total = v1Out + v2Out + v3Out; - switch ( total ) { - case 0: { - // the entire face lies inside of the plane, no clipping needed + switch (total) + { + case 0: + { + // The entire face lies inside of the plane, no clipping needed AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]}); - break; - } - - case 1: { - // one vertex lies outside of the plane, perform clipping - - if (v1Out) { - nV1 = inMesh->vertices[ i + 1 ]; - nV2 = inMesh->vertices[ i + 2 ]; - nV3 = ClipSegment( inMesh->vertices[ i ], nV1, planes[face], s ); - nV4 = ClipSegment( inMesh->vertices[ i ], nV2, planes[face], s ); + } break; + case 1: + { + // One vertex lies outside of the plane, perform clipping + if (v1Out) + { + nV1 = inMesh->vertices[i + 1]; + nV2 = inMesh->vertices[i + 2]; + nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s); } - if (v2Out) { - nV1 = inMesh->vertices[ i ]; - nV2 = inMesh->vertices[ i + 2 ]; - nV3 = ClipSegment( inMesh->vertices[ i + 1 ], nV1, planes[face], s ); - nV4 = ClipSegment( inMesh->vertices[ i + 1 ], nV2, planes[face], s ); + if (v2Out) + { + nV1 = inMesh->vertices[i]; + nV2 = inMesh->vertices[i + 2]; + nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1}); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4}); break; } - if (v3Out) { - nV1 = inMesh->vertices[ i ]; - nV2 = inMesh->vertices[ i + 1 ]; - nV3 = ClipSegment( inMesh->vertices[ i + 2 ], nV1, planes[face], s ); - nV4 = ClipSegment( inMesh->vertices[ i + 2 ], nV2, planes[face], s ); + if (v3Out) + { + nV1 = inMesh->vertices[i]; + nV2 = inMesh->vertices[i + 1]; + nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s); } AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2}); - - break; - } - - case 2: { - // two vertices lies outside of the plane, perform clipping - if (!v1Out) { - nV1 = inMesh->vertices[ i ]; - nV2 = ClipSegment( nV1, inMesh->vertices[ i + 1 ], planes[face], s ); - nV3 = ClipSegment( nV1, inMesh->vertices[ i + 2 ], planes[face], s ); + } break; + case 2: + { + // Two vertices lies outside of the plane, perform clipping + if (!v1Out) + { + nV1 = inMesh->vertices[i]; + nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); } - if (!v2Out) { - nV1 = inMesh->vertices[ i + 1 ]; - nV2 = ClipSegment( nV1, inMesh->vertices[ i + 2 ], planes[face], s ); - nV3 = ClipSegment( nV1, inMesh->vertices[ i ], planes[face], s ); + + if (!v2Out) + { + nV1 = inMesh->vertices[i + 1]; + nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); } - if (!v3Out) { - nV1 = inMesh->vertices[ i + 2 ]; - nV2 = ClipSegment( nV1, inMesh->vertices[ i ], planes[face], s ); - nV3 = ClipSegment( nV1, inMesh->vertices[ i + 1 ], planes[face], s ); + + if (!v3Out) + { + nV1 = inMesh->vertices[i + 2]; + nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); } - break; - } - - case 3: { - // the entire face lies outside of the plane, so let's discard the corresponding vertices - break; - } - + } break; + case 3: // The entire face lies outside of the plane, so let's discard the corresponding vertices + default: break; } } } // Now we just need to re-transform the vertices - MeshBuilder *theMesh = &mesh_builders[mb_index]; + MeshBuilder *theMesh = &meshBuilders[mbIndex]; // Allocate room for UVs if (theMesh->vertexCount > 0) { - theMesh->uvs = (Vector2*)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); + theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); + for (int i = 0; i < theMesh->vertexCount; i++) { - // Calculate the UVs based on the projected coords // They are clipped to (-decalSize .. decalSize) and we want them (0..1) - theMesh->uvs[i].x = (theMesh->vertices[i].x / decalSize + .5f); - theMesh->uvs[i].y = (theMesh->vertices[i].y / decalSize + .5f); + theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f); + theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f); // From splat space to world space theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], splatInv); @@ -378,89 +366,73 @@ int main(void) decalModels[decalIndex] = LoadModelFromMesh(BuildMesh(theMesh)); decalModels[decalIndex].materials[0] = decalMaterial; } - } - //---------------------------------------------------------------------------------- // Draw //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(RAYWHITE); BeginMode3D(camera); - // Draw the model at the origin and default scale - if (showModel) - { - DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE); - } + if (showModel) DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE); // Draw the decal models - for (int i = 0; i < decalCount; i++) - { - DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE); - } + for (int i = 0; i < decalCount; i++) DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE); // If we hit the mesh, draw the box for the decal if (collision.hit) { - Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){0,1,0}); - placementCube.transform = MatrixInvert(splat); DrawModel(placementCube, (Vector3){0}, 1.0f, Fade(WHITE, 0.5f)); } DrawGrid(10, 10.0f); - EndMode3D(); + + float yPos = 10; + float x0 = GetScreenWidth() - 300; + float x1 = x0 + 100; + float x2 = x1 + 100; + DrawText("Vertices", x1, yPos, 10, LIME); + DrawText("Triangles", x2, yPos, 10, LIME); + yPos += 15; + + int vertexCount = 0; + int triangleCount = 0; + + for (int i = 0; i < model.meshCount; i++) { - float yPos = 10; - float x0 = GetScreenWidth() - 300; - float x1 = x0 + 100; - float x2 = x1 + 100; + vertexCount += model.meshes[i].vertexCount; + triangleCount += model.meshes[i].triangleCount; + } + + DrawText("Main model", x0, yPos, 10, LIME); + DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); + yPos += 15; + + for (int i = 0; i < decalCount; i++) + { + DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); - DrawText("Vertices", x1, yPos, 10, LIME); - DrawText("Triangles", x2, yPos, 10, LIME); - yPos += 15; - - int vertexCount = 0; - int triangleCount = 0; - - for (int i = 0; i < model.meshCount; i++) - { - vertexCount += model.meshes[i].vertexCount; - triangleCount += model.meshes[i].triangleCount; - } - - DrawText("Main model", x0, yPos, 10, LIME); - DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); - DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); - yPos += 15; - - for (int i = 0; i < decalCount; i++) - { - DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); - DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); - DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); - - vertexCount += decalModels[i].meshes[0].vertexCount; - triangleCount += decalModels[i].meshes[0].triangleCount; - yPos += 15; - } - - DrawText("TOTAL", x0, yPos, 10, LIME); - DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); - DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); + vertexCount += decalModels[i].meshes[0].vertexCount; + triangleCount += decalModels[i].meshes[0].triangleCount; yPos += 15; } + + DrawText("TOTAL", x0, yPos, 10, LIME); + DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); + yPos += 15; DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); - DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); DrawFPS(10, 10); @@ -474,15 +446,13 @@ int main(void) UnloadModel(model); UnloadTexture(modelTexture); - for (int i = 0; i < decalCount; i++) - { - UnloadModel(decalModels[i]); - } - + // TODO: WARNING: This line crashes program on closing + //for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); + UnloadTexture(decalTexture); - FreeMeshBuilder(&mesh_builders[0]); - FreeMeshBuilder(&mesh_builders[1]); + FreeMeshBuilder(&meshBuilders[0]); + FreeMeshBuilder(&meshBuilders[1]); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- @@ -490,18 +460,24 @@ int main(void) return 0; } -// A really simple dynamic array manager -void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]) { +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +// Add triangles to mesh builder (dynamic array manager) +static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]) +{ // Reallocate and copy if we need to - if (mb->vertexCapacity <= mb->vertexCount + 3 ) + if (mb->vertexCapacity <= (mb->vertexCount + 3)) { - int newVertexCapacity = (1 + (mb->vertexCapacity / 256)) * 256; - Vector3 *newVertices = (Vector3*)MemAlloc(newVertexCapacity * sizeof(Vector3)); + int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256; + Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3)); + if (mb->vertexCapacity > 0) { - memcpy(newVertices, mb->vertices, mb->vertexCount * sizeof(Vector3)); + memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3)); MemFree(mb->vertices); } + mb->vertices = newVertices; mb->vertexCapacity = newVertexCapacity; } @@ -510,44 +486,33 @@ void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]) { int index = mb->vertexCount; mb->vertexCount += 3; - for (int i = 0; i < 3; i++) - { - mb->vertices[index+i] = vertices[i]; - } + for (int i = 0; i < 3; i++) mb->vertices[index+i] = vertices[i]; } -void FreeMeshBuilder(MeshBuilder *mb) +// Free mesh builder +static void FreeMeshBuilder(MeshBuilder *mb) { MemFree(mb->vertices); - - if (mb->uvs) - { - MemFree(mb->uvs); - } - + if (mb->uvs) MemFree(mb->uvs); *mb = (MeshBuilder){ 0 }; } -// Construct a Raylib Mesh from our MeshBuilder data -Mesh BuildMesh(MeshBuilder *mb) +// Build a Mesh from MeshBuilder data +static Mesh BuildMesh(MeshBuilder *mb) { Mesh outMesh = { 0 }; outMesh.vertexCount = mb->vertexCount; - outMesh.triangleCount = mb->vertexCount / 3; - - outMesh.vertices = MemAlloc(outMesh.vertexCount * 3 * sizeof(float)); - - if (mb->uvs) - { - outMesh.texcoords = MemAlloc(outMesh.vertexCount * 2 * sizeof(float)); - } - + outMesh.triangleCount = mb->vertexCount/3; + outMesh.vertices = MemAlloc(outMesh.vertexCount*3*sizeof(float)); + if (mb->uvs) outMesh.texcoords = MemAlloc(outMesh.vertexCount*2*sizeof(float)); + for (int i = 0; i < mb->vertexCount; i++) { outMesh.vertices[3*i+0] = mb->vertices[i].x; outMesh.vertices[3*i+1] = mb->vertices[i].y; outMesh.vertices[3*i+2] = mb->vertices[i].z; + if (mb->uvs) { outMesh.texcoords[2*i+0] = mb->uvs[i].x; @@ -560,14 +525,14 @@ Mesh BuildMesh(MeshBuilder *mb) return outMesh; } -Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) +// Clip segment +static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) { float d0 = Vector3DotProduct(v0, p) - s; float d1 = Vector3DotProduct(v1, p) - s; - - float s0 = d0 / ( d0 - d1 ); + float s0 = d0/(d0 - d1); Vector3 position = Vector3Lerp(v0, v1, s0); return position; -} \ No newline at end of file +} From 6f101f40110cf1e5f49792ec2bf1ae4dfa0d3ab6 Mon Sep 17 00:00:00 2001 From: Jopestpe <47086979+Jopestpe@users.noreply.github.com> Date: Sat, 25 Oct 2025 08:38:06 -0300 Subject: [PATCH 069/102] [examples] Added: `shapes_math_sine_cosine` (#5257) * draft: [examples] Added shapes_math_sine_cosine * draft: [examples] Added screenshot shapes_math_sine_cosine * Explementary * Varying radius * adjustments * added comments and reorganized UI labels * Updated Makefile, README.md, and examples_list.txt * tabs to spaces * Fix MSVC compilation --------- Co-authored-by: Ray --- examples/Makefile | 1 + examples/Makefile.Web | 4 + examples/README.md | 2 +- examples/examples_list.txt | 1 + examples/shapes/shapes_math_sine_cosine.c | 176 ++++++++++++++++++++ examples/shapes/shapes_math_sine_cosine.png | Bin 0 -> 22098 bytes 6 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 examples/shapes/shapes_math_sine_cosine.c create mode 100644 examples/shapes/shapes_math_sine_cosine.png diff --git a/examples/Makefile b/examples/Makefile index ef7cb5948..9ae8bb480 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -564,6 +564,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_sine_cosine \ shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 5d4f3ffab..0e9b9f92f 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -564,6 +564,7 @@ SHAPES = \ shapes/shapes_lines_bezier \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_sine_cosine \ shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ shapes/shapes_rectangle_advanced \ @@ -899,6 +900,9 @@ shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_mouse_trail: shapes/shapes_mouse_trail.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) diff --git a/examples/README.md b/examples/README.md index 19d110344..bbb0a0388 100644 --- a/examples/README.md +++ b/examples/README.md @@ -71,7 +71,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | | [core_text_file_loading](core/core_text_file_loading.c) | core_text_file_loading | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) | -### category: shapes [31] +### category: shapes [32] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 71cda6c1a..4805a37ec 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -80,6 +80,7 @@ shapes;shapes_vector_angle;★★☆☆;1.0;5.0;2023;2025;"Ramon Santamaria";@ra shapes;shapes_pie_chart;★★★☆;5.5;5.6;2025;2025;"Gideon Serfontein";@GideonSerf shapes;shapes_kaleidoscope;★★☆☆;5.5;5.6;2025;2025;"Hugo ARNAL";@hugoarnal shapes;shapes_clock_of_clocks;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates +shapes;shapes_math_sine_cosine;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814 shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates diff --git a/examples/shapes/shapes_math_sine_cosine.c b/examples/shapes/shapes_math_sine_cosine.c new file mode 100644 index 000000000..f61d4f548 --- /dev/null +++ b/examples/shapes/shapes_math_sine_cosine.c @@ -0,0 +1,176 @@ +/******************************************************************************************* +* +* raylib [shapes] example - math sine cosine +* +* Example complexity rating: [★★☆☆] 2/4 +* +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev +* +* Example contributed by Jopestpe (@jopestpe) +* +* 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) 2025-2025 Jopestpe (@jopestpe) +* +********************************************************************************************/ + +#include "raylib.h" +#include +#include "raymath.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" // Required for GUI controls + +// Wave points for sine/cosine visualization +#define WAVE_POINTS 36 + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math sine cosine"); + + Vector2 sinePoints[WAVE_POINTS]; + Vector2 cosPoints[WAVE_POINTS]; + Vector2 center = { (screenWidth/2.0f) - 30.f, screenHeight/2.0f }; + Rectangle start = { 20.f, screenHeight - 120.f , 200.0f, 100.0f}; + float radius = 130.0f; + float angle = 0.0f; + bool pause = false; + + for (int i = 0; i < WAVE_POINTS; i++) + { + float t = i/(float)(WAVE_POINTS - 1); + float currentAngle = t*360.0f*DEG2RAD; + sinePoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - sinf(currentAngle)*(start.height/2.0f) }; + cosPoints[i] = (Vector2){ start.x + t*start.width, start.y + start.height/2.0f - cosf(currentAngle)*(start.height/2.0f) }; + } + + 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 + //---------------------------------------------------------------------------------- + float angleRad = angle*DEG2RAD; + float cosRad = cosf(angleRad); + float sinRad = sinf(angleRad); + + Vector2 point = { center.x + cosRad*radius, center.y - sinRad*radius }; + Vector2 limitMin = { center.x - radius, center.y - radius }; + Vector2 limitMax = { center.x + radius, center.y + radius }; + + float complementary = 90.0f - angle; + float supplementary = 180.0f - angle; + float explementary = 360.0f - angle; + + float tangent = Clamp(tanf(angleRad), -10.0f, 10.0f); + float cotangent = (fabsf(tangent) > 0.001f) ? Clamp(1.0f/tangent, -radius, radius) : 0.0f; + Vector2 tangentPoint = { center.x + radius, center.y - tangent*radius }; + Vector2 cotangentPoint = { center.x + cotangent*radius, center.y - radius }; + + angle = Wrap(angle + (!pause ? 1.0f : 0.0f), 0.0f, 360.0f); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(RAYWHITE); + + // Cotangent (orange) + DrawLineEx((Vector2){ center.x , limitMin.y }, (Vector2){ cotangentPoint.x, limitMin.y }, 2.0f, ORANGE); + DrawLineDashed(center, cotangentPoint, 10.0f, 4.0f, ORANGE); + + // Side background + DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); + DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 }); + + // Base circle and axes + DrawCircleLinesV(center, radius, GRAY); + DrawLineEx((Vector2){ center.x, limitMin.y }, (Vector2){ center.x, limitMax.y }, 1.0f, GRAY); + DrawLineEx((Vector2){ limitMin.x, center.y }, (Vector2){ limitMax.x, center.y }, 1.f, GRAY); + + // Wave graph axes + DrawLineEx((Vector2){ start.x , start.y }, (Vector2){ start.x , start.y + start.height }, 2.0f, GRAY); + DrawLineEx((Vector2){ start.x + start.width, start.y }, (Vector2){ start.x + start.width, start.y + start.height }, 2.0f, GRAY); + DrawLineEx((Vector2){ start.x, start.y + start.height/2 }, (Vector2){ start.x + start.width, start.y + start.height/2 }, 2.0f, GRAY); + + // Wave graph axis labels + DrawText("1", start.x - 8, start.y, 6, GRAY); + DrawText("0", start.x - 8, start.y + start.height/2 - 6, 6, GRAY); + DrawText("-1", start.x - 12, start.y + start.height - 8, 6, GRAY); + DrawText("0", start.x - 2, start.y + start.height + 4, 6, GRAY); + DrawText("360", start.x + start.width - 8, start.y + start.height + 4, 6, GRAY); + + // Sine (red - vertical) + DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ center.x, point.y }, 2.0f, RED); + DrawLineDashed((Vector2){ point.x, center.y }, (Vector2){ point.x, point.y }, 10.0f, 4.0f, RED); + DrawText(TextFormat("Sine %.2f", sinRad), 640, 190, 6, RED); + DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-sinRad + 1)*start.height/2.0f) }, 4.0f, RED); + DrawSplineLinear(sinePoints, WAVE_POINTS, 1.0f, RED); + + // Cosine (blue - horizontal) + DrawLineEx((Vector2){ center.x, center.y }, (Vector2){ point.x, center.y }, 2.0f, BLUE); + DrawLineDashed((Vector2){ center.x , point.y }, (Vector2){ point.x, point.y }, 10.0f, 4.0f, BLUE); + DrawText(TextFormat("Cosine %.2f", cosRad), 640, 210, 6, BLUE); + DrawCircleV((Vector2){ start.x + (angle/360.0f)*start.width, start.y + ((-cosRad + 1)*start.height/2.0f) }, 4.0f, BLUE); + DrawSplineLinear(cosPoints, WAVE_POINTS, 1.0f, BLUE); + + // Tangent (purple) + DrawLineEx((Vector2){ limitMax.x , center.y }, (Vector2){ limitMax.x, tangentPoint.y }, 2.0f, PURPLE); + DrawLineDashed(center, tangentPoint, 10.0f, 4.0f, PURPLE); + DrawText(TextFormat("Tangent %.2f", tangent), 640, 230, 6, PURPLE); + + // Cotangent (orange) + DrawText(TextFormat("Cotangent %.2f", cotangent), 640, 250, 6, ORANGE); + + // Complementary angle (beige) + DrawCircleSectorLines(center, radius*0.6f , -angle, -90.f , 36.0f, BEIGE); + DrawText(TextFormat("Complementary %0.f°",complementary), 640, 150, 6, BEIGE); + + // Supplementary angle (darkblue) + DrawCircleSectorLines(center, radius*0.5f , -angle, -180.f , 36.0f, DARKBLUE); + DrawText(TextFormat("Supplementary %0.f°",supplementary), 640, 130, 6, DARKBLUE); + + // Explementary angle (pink) + DrawCircleSectorLines(center, radius*0.4f , -angle, -360.f , 36.0f, PINK); + DrawText(TextFormat("Explementary %0.f°",explementary), 640, 170, 6, PINK); + + // Current angle - arc (lime), radius (black), endpoint (black) + DrawCircleSectorLines(center, radius*0.7f , -angle, 0.f, 36.0f, LIME); + DrawLineEx((Vector2){ center.x , center.y }, point, 2.0f, BLACK); + DrawCircleV(point, 4.0f, BLACK); + + // Draw GUI controls + //------------------------------------------------------------------------------ + GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GRAY)); + GuiToggle((Rectangle){ 640, 70, 120, 20}, TextFormat("Pause"), &pause); + GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(LIME)); + GuiSliderBar((Rectangle){ 640, 40, 120, 20}, "Angle", TextFormat("%.0f°", angle), &angle, 0.0f, 360.f); + + // Angle values panel + GuiGroupBox((Rectangle){ 620, 110, 140, 170}, "Angle Values"); + //------------------------------------------------------------------------------ + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/shapes/shapes_math_sine_cosine.png b/examples/shapes/shapes_math_sine_cosine.png new file mode 100644 index 0000000000000000000000000000000000000000..b561f74fbbd06ab006df7e5789e79a6cba255b07 GIT binary patch literal 22098 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 literal 0 HcmV?d00001 From a25d11ad1a3d7c5660127229a3a9ffd62a2225e4 Mon Sep 17 00:00:00 2001 From: Kris Date: Sat, 25 Oct 2025 17:12:35 +0530 Subject: [PATCH 070/102] Add example: shapes_math_angle_rotation (angle rotation lines) (#5236) Co-authored-by: Ray --- examples/shaders/shaders_palette_switch.c | 4 +- examples/shapes/shapes_math_angle_rotation.c | 102 ++++ .../shapes/shapes_math_angle_rotation.png | Bin 0 -> 4869 bytes .../shapes_math_angle_rotation.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 2 + 5 files changed, 675 insertions(+), 2 deletions(-) create mode 100644 examples/shapes/shapes_math_angle_rotation.c create mode 100644 examples/shapes/shapes_math_angle_rotation.png create mode 100644 projects/VS2022/examples/shapes_math_angle_rotation.vcxproj diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index 048fe7fbc..e23cad1d3 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [shaders] example - palette switch +* raylib [shaders] example - palette switch * * Example complexity rating: [★★★☆] 3/4 * @@ -11,7 +11,7 @@ * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * -* Example originally created with raylib 2.5, last time updated with raylib 3.7 +* Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Marco Lizza (@MarcoLizza) and reviewed by Ramon Santamaria (@raysan5) * diff --git a/examples/shapes/shapes_math_angle_rotation.c b/examples/shapes/shapes_math_angle_rotation.c new file mode 100644 index 000000000..0e4802064 --- /dev/null +++ b/examples/shapes/shapes_math_angle_rotation.c @@ -0,0 +1,102 @@ +/******************************************************************************************* +* +* raylib [shapes] example - Math angle rotation lines +* +* Example complexity rating: [★☆☆☆] 1/4 +* +* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* +* Example contributed by Kris (@krispy-snacc) and reviewed by Ramon Santamaria (@raysan5) +* +* Example licensed under an unmodified zlib/libpng license +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" // for DEG2RAD + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 720; + const int screenHeight = 400; + + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - angle rotation lines"); + SetTargetFPS(60); + + Vector2 center = { screenWidth / 2.0f, screenHeight / 2.0f }; + const float lineLength = 150.0f; + + // Predefined angles for fixed lines + int angles[] = { 0, 30, 60, 90 }; + int numAngles = sizeof(angles)/sizeof(angles[0]); + + float totalAngle = 0.0f; // Animated rotation angle + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) + { + // Update + //---------------------------------------------------------------------------------- + totalAngle += 1.0f; // degrees per frame + if (totalAngle >= 360.0f) totalAngle -= 360.0f; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + ClearBackground(WHITE); + + DrawText("Fixed angles + rotating line", 10, 10, 20, LIGHTGRAY); + + // Draw fixed-angle lines with colorful gradient + for (int i = 0; i < numAngles; i++) + { + float rad = angles[i] * DEG2RAD; + Vector2 end = { center.x + cosf(rad) * lineLength, + center.y + sinf(rad) * lineLength }; + + // Gradient color from green → cyan → blue → magenta + Color col; + switch(i) + { + case 0: col = GREEN; break; + case 1: col = ORANGE; break; + case 2: col = BLUE; break; + case 3: col = MAGENTA; break; + default: col = WHITE; break; + } + + DrawLineEx(center, end, 5.0f, col); + + // Draw angle label slightly offset along the line + Vector2 textPos = { center.x + cosf(rad) * (lineLength + 20), + center.y + sinf(rad) * (lineLength + 20) }; + DrawText(TextFormat("%d°", angles[i]), (int)textPos.x, (int)textPos.y, 20, col); + } + + // Draw animated rotating line with changing color + float animRad = totalAngle * DEG2RAD; + Vector2 animEnd = { center.x + cosf(animRad) * lineLength, + center.y + sinf(animRad) * lineLength }; + + // Cycle through HSV colors for animated line + Color animCol = ColorFromHSV(fmodf(totalAngle, 360.0f), 0.8f, 0.9f); + DrawLineEx(center, animEnd, 5.0f, animCol); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shapes/shapes_math_angle_rotation.png b/examples/shapes/shapes_math_angle_rotation.png new file mode 100644 index 0000000000000000000000000000000000000000..fd9a92360b6c2f187c91324a3b2005bb83471e5d GIT binary patch literal 4869 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 TY^lb;z`)??>gTe~DWM4fetn1b literal 0 HcmV?d00001 diff --git a/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj b/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj new file mode 100644 index 000000000..0bee76192 --- /dev/null +++ b/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {6B1A933E-71B8-4C1F-9E79-02D98830E671} + Win32Proj + shapes_math_angle_rotation + 10.0 + shapes_math_angle_rotation + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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) + /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 + 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)\ + + + + + 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 + + + + + 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 ec35ed5e5..8d2704abf 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -395,6 +395,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_mandelbrot_set", "examples\shaders_mandelbrot_set.vcxproj", "{1C829D1A-892C-451C-AF0B-AC65C85F5CC6}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_angle_rotation", "examples\shapes_math_angle_rotation.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 From e501dfad60791346ade0cd389fd04e20e97d427f Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Sat, 25 Oct 2025 23:13:24 +0200 Subject: [PATCH 071/102] [rlsw] Subpixel correction (#5300) * fix triangle cracking * subpixel corretion for quads * replace Bresenham for DDA + subpixel correction * consistency * adding note * style tweaks --- src/external/rlsw.h | 502 ++++++++++++++++++++++---------------------- 1 file changed, 252 insertions(+), 250 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index bc7a813d3..50a60d74f 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -819,8 +819,8 @@ typedef struct { float clearColor[4]; // Color used to clear the screen float clearDepth; // Depth value used to clear the screen - int vpCenter[2]; // Viewport center - int vpHalfSize[2]; // Viewport half dimensions + float vpCenter[2]; // Viewport center + float vpHalf[2]; // Viewport half dimensions int vpSize[2]; // Viewport dimensions (minus one) int vpMin[2]; // Viewport minimum renderable point (top-left) int vpMax[2]; // Viewport maximum renderable point (bottom-right) @@ -1040,6 +1040,34 @@ static inline void sw_add_vertex_grad_PTCH(sw_vertex_t *SW_RESTRICT out, const s out->homogeneous[3] += gradients->homogeneous[3]; } +static inline void sw_add_vertex_grad_scaled_PTCH( + sw_vertex_t *SW_RESTRICT out, + const sw_vertex_t *SW_RESTRICT gradients, + float scale) +{ + // Add gradients to Position + out->position[0] += gradients->position[0]*scale; + out->position[1] += gradients->position[1]*scale; + out->position[2] += gradients->position[2]*scale; + out->position[3] += gradients->position[3]*scale; + + // Add gradients to Texture coordinates + out->texcoord[0] += gradients->texcoord[0]*scale; + out->texcoord[1] += gradients->texcoord[1]*scale; + + // Add gradients to Color + out->color[0] += gradients->color[0]*scale; + out->color[1] += gradients->color[1]*scale; + out->color[2] += gradients->color[2]*scale; + out->color[3] += gradients->color[3]*scale; + + // Add gradients to Homogeneous coordinates + out->homogeneous[0] += gradients->homogeneous[0]*scale; + out->homogeneous[1] += gradients->homogeneous[1]*scale; + out->homogeneous[2] += gradients->homogeneous[2]*scale; + out->homogeneous[3] += gradients->homogeneous[3]*scale; +} + static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) { #if defined(SW_HAS_NEON) @@ -1977,18 +2005,18 @@ static inline void sw_texture_sample_linear(float *color, const sw_texture_t *te } } -static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float duDx, float duDy, float dvDx, float dvDy) +static inline void sw_texture_sample(float *color, const sw_texture_t *tex, float u, float v, float dUdx, float dUdy, float dVdx, float dVdy) { // Previous method: There is no need to compute the square root // because using the squared value, the comparison remains `L2 > 1.0f*1.0f` - //float du = sqrtf(duDx*duDx + duDy*duDy); - //float dv = sqrtf(dvDx*dvDx + dvDy*dvDy); + //float du = sqrtf(dUdx*dUdx + dUdy*dUdy); + //float dv = sqrtf(dVdx*dVdx + dVdy*dVdy); //float L = (du > dv)? du : dv; // Calculate the derivatives for each axis - float du2 = duDx*duDx + duDy*duDy; - float dv2 = dvDx*dvDx + dvDy*dvDy; - float L2 = (du2 > dv2)? du2 : dv2; + float dU2 = dUdx*dUdx + dUdy*dUdy; + float dV2 = dVdx*dVdx + dVdy*dVdy; + float L2 = (dU2 > dV2)? dU2 : dV2; SWfilter filter = (L2 > 1.0f)? tex->minFilter : tex->magFilter; @@ -2081,8 +2109,8 @@ static inline void sw_blend_colors(float *SW_RESTRICT dst/*[4]*/, const float *S //------------------------------------------------------------------------------------------- static inline void sw_project_ndc_to_screen(float screen[2], const float ndc[4]) { - screen[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalfSize[0]; - screen[1] = RLSW.vpCenter[1] - ndc[1]*RLSW.vpHalfSize[1]; + screen[0] = RLSW.vpCenter[0] + ndc[0]*RLSW.vpHalf[0] + 0.5f; + screen[1] = RLSW.vpCenter[1] - ndc[1]*RLSW.vpHalf[1] + 0.5f; } //------------------------------------------------------------------------------------------- @@ -2295,67 +2323,73 @@ static inline void sw_triangle_clip_and_project(void) #define DEFINE_TRIANGLE_RASTER_SCANLINE(FUNC_NAME, ENABLE_TEXTURE, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \ - const sw_vertex_t *end, float duDy, float dvDy) \ + const sw_vertex_t *end, float dUdy, float dVdy) \ { \ - /* Convert and center the screen coordinates */ \ - int xStart = (int)(start->screen[0] + 0.5f); \ - int xEnd = (int)(end->screen[0] + 0.5f); \ - int y = (int)start->screen[1]; \ + /* Gets the start and end coordinates */ \ + int xStart = (int)start->screen[0]; \ + int xEnd = (int)end->screen[0]; \ + \ + /* Avoid empty lines */ \ + if (xStart == xEnd) return; \ + \ + /* Compute the subpixel distance to traverse before the first pixel */ \ + float xSubstep = 1.0f - sw_fract(start->screen[0]); \ \ /* Compute the inverse horizontal distance along the X axis */ \ - float dx = end->screen[0] - start->screen[0]; \ - if (fabsf(dx) < 1e-6f) return; \ - float dxRcp = 1.0f/dx; \ + float dxRcp = 1.0f/(end->screen[0] - start->screen[0]); \ \ /* Compute the interpolation steps along the X axis */ \ - float dzDx = (end->homogeneous[2] - start->homogeneous[2])*dxRcp; \ - float dwDx = (end->homogeneous[3] - start->homogeneous[3])*dxRcp; \ + float dZdx = (end->homogeneous[2] - start->homogeneous[2])*dxRcp; \ + float dWdx = (end->homogeneous[3] - start->homogeneous[3])*dxRcp; \ \ - float dcDx[4] = { 0 }; \ - dcDx[0] = (end->color[0] - start->color[0])*dxRcp; \ - dcDx[1] = (end->color[1] - start->color[1])*dxRcp; \ - dcDx[2] = (end->color[2] - start->color[2])*dxRcp; \ - dcDx[3] = (end->color[3] - start->color[3])*dxRcp; \ + float dCdx[4] = { \ + (end->color[0] - start->color[0])*dxRcp, \ + (end->color[1] - start->color[1])*dxRcp, \ + (end->color[2] - start->color[2])*dxRcp, \ + (end->color[3] - start->color[3])*dxRcp \ + }; \ \ - float duDx = 0.0f, dvDx = 0.0f; \ + float dUdx = 0.0f; \ + float dVdx = 0.0f; \ if (ENABLE_TEXTURE) { \ - duDx = (end->texcoord[0] - start->texcoord[0])*dxRcp; \ - dvDx = (end->texcoord[1] - start->texcoord[1])*dxRcp; \ + dUdx = (end->texcoord[0] - start->texcoord[0])*dxRcp; \ + dVdx = (end->texcoord[1] - start->texcoord[1])*dxRcp; \ } \ \ /* Initializing the interpolation starting values */ \ - float z = start->homogeneous[2]; \ - float w = start->homogeneous[3]; \ + float z = start->homogeneous[2] + dZdx*xSubstep; \ + float w = start->homogeneous[3] + dWdx*xSubstep; \ \ - float color[4] = { 0 }; \ - color[0] = start->color[0]; \ - color[1] = start->color[1]; \ - color[2] = start->color[2]; \ - color[3] = start->color[3]; \ + float color[4] = { \ + start->color[0] + dCdx[0]*xSubstep, \ + start->color[1] + dCdx[1]*xSubstep, \ + start->color[2] + dCdx[2]*xSubstep, \ + start->color[3] + dCdx[3]*xSubstep \ + }; \ \ - float u = 0.0f, v = 0.0f; \ + float u = 0.0f; \ + float v = 0.0f; \ if (ENABLE_TEXTURE) { \ - u = start->texcoord[0]; \ - v = start->texcoord[1]; \ + u = start->texcoord[0] + dUdx*xSubstep; \ + v = start->texcoord[1] + dVdx*xSubstep; \ } \ \ /* Pre-calculate the starting pointers for the framebuffer row */ \ + int y = (int)start->screen[1]; \ void *cptr = GET_COLOR_PTR(RLSW.framebuffer.color, y*RLSW.framebuffer.width + xStart); \ void *dptr = GET_DEPTH_PTR(RLSW.framebuffer.depth, y*RLSW.framebuffer.width + xStart); \ \ /* Scanline rasterization */ \ for (int x = xStart; x < xEnd; x++) \ { \ - /* Pixel color computation */ \ float wRcp = 1.0f/w; \ float srcColor[4] = { \ - color[0]*wRcp, \ - color[1]*wRcp, \ - color[2]*wRcp, \ - color[3]*wRcp \ + color[0]*wRcp, \ + color[1]*wRcp, \ + color[2]*wRcp, \ + color[3]*wRcp \ }; \ \ - /* Test and write depth */ \ if (ENABLE_DEPTH_TEST) \ { \ /* TODO: Implement different depth funcs? */ \ @@ -2363,6 +2397,7 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, if (z > depth) goto discard; \ } \ \ + /* TODO: Implement depth mask */ \ sw_framebuffer_write_depth(dptr, z); \ \ if (ENABLE_TEXTURE) \ @@ -2370,7 +2405,7 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, float texColor[4]; \ float s = u*wRcp; \ float t = v*wRcp; \ - sw_texture_sample(texColor, tex, s, t, duDx, duDy, dvDx, dvDy); \ + sw_texture_sample(texColor, tex, s, t, dUdx, dUdy, dVdx, dVdy); \ srcColor[0] *= texColor[0]; \ srcColor[1] *= texColor[1]; \ srcColor[2] *= texColor[2]; \ @@ -2391,16 +2426,16 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \ /* Increment the interpolation parameter, UVs, and pointers */ \ discard: \ - z += dzDx; \ - w += dwDx; \ - color[0] += dcDx[0]; \ - color[1] += dcDx[1]; \ - color[2] += dcDx[2]; \ - color[3] += dcDx[3]; \ + z += dZdx; \ + w += dWdx; \ + color[0] += dCdx[0]; \ + color[1] += dCdx[1]; \ + color[2] += dCdx[2]; \ + color[3] += dCdx[3]; \ if (ENABLE_TEXTURE) \ { \ - u += duDx; \ - v += dvDx; \ + u += dUdx; \ + v += dVdx; \ } \ \ INC_COLOR_PTR(cptr); \ @@ -2430,60 +2465,71 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1, if (h02 < 1e-6f) return; \ \ /* Precompute the inverse values without additional checks */ \ - float invH02 = 1.0f/h02; \ - float invH01 = (h01 > 1e-6f)? 1.0f/h01 : 0.0f; \ - float invH12 = (h12 > 1e-6f)? 1.0f/h12 : 0.0f; \ + float h02Rcp = 1.0f/h02; \ + float h01Rcp = (h01 > 1e-6f)? 1.0f/h01 : 0.0f; \ + float h12Rcp = (h12 > 1e-6f)? 1.0f/h12 : 0.0f; \ \ /* Pre-calculation of slopes */ \ - float dx02 = (x2 - x0)*invH02; \ - float dx01 = (x1 - x0)*invH01; \ - float dx12 = (x2 - x1)*invH12; \ + float dXdy02 = (x2 - x0)*h02Rcp; \ + float dXdy01 = (x1 - x0)*h01Rcp; \ + float dXdy12 = (x2 - x1)*h12Rcp; \ + \ + /* Y subpixel correction */ \ + float y0Substep = 1.0f - sw_fract(y0); \ + float y1Substep = 1.0f - sw_fract(y1); \ \ /* Y bounds (vertical clipping) */ \ - int yTop = (int)(y0 + 0.5f); \ - int yMiddle = (int)(y1 + 0.5f); \ - int yBottom = (int)(y2 + 0.5f); \ + int yTop = (int)y0; \ + int yMid = (int)y1; \ + int yBot = (int)y2; \ \ /* Compute gradients for each side of the triangle */ \ - sw_vertex_t vDy02, vDy01, vDy12; \ - sw_get_vertex_grad_PTCH(&vDy02, v0, v2, invH02); \ - sw_get_vertex_grad_PTCH(&vDy01, v0, v1, invH01); \ - sw_get_vertex_grad_PTCH(&vDy12, v1, v2, invH12); \ + sw_vertex_t dVXdy02, dVXdy01, dVXdy12; \ + sw_get_vertex_grad_PTCH(&dVXdy02, v0, v2, h02Rcp); \ + sw_get_vertex_grad_PTCH(&dVXdy01, v0, v1, h01Rcp); \ + sw_get_vertex_grad_PTCH(&dVXdy12, v1, v2, h12Rcp); \ \ - /* Initializing scanline variables */ \ - sw_vertex_t vLeft = *v0; \ - vLeft.screen[0] = x0; \ - sw_vertex_t vRight = *v0; \ - vRight.screen[0] = x0; \ + /* Get a copy of vertices for interpolation and apply substep correction */ \ + sw_vertex_t vLeft = *v0, vRight = *v0; \ + sw_add_vertex_grad_scaled_PTCH(&vLeft, &dVXdy02, y0Substep); \ + sw_add_vertex_grad_scaled_PTCH(&vRight, &dVXdy01, y0Substep); \ + \ + vLeft.screen[0] += dXdy02*y0Substep; \ + vRight.screen[0] += dXdy01*y0Substep; \ \ /* Scanline for the upper part of the triangle */ \ - for (int y = yTop; y < yMiddle; y++) \ + for (int y = yTop; y < yMid; y++) \ { \ vLeft.screen[1] = vRight.screen[1] = y; \ \ - if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, vDy02.texcoord[0], vDy02.texcoord[1]); \ - else FUNC_SCANLINE(tex, &vRight, &vLeft, vDy02.texcoord[0], vDy02.texcoord[1]); \ + if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \ + else FUNC_SCANLINE(tex, &vRight, &vLeft, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \ \ - sw_add_vertex_grad_PTCH(&vLeft, &vDy02); \ - vLeft.screen[0] += dx02; \ - sw_add_vertex_grad_PTCH(&vRight, &vDy01); \ - vRight.screen[0] += dx01; \ + sw_add_vertex_grad_PTCH(&vLeft, &dVXdy02); \ + vLeft.screen[0] += dXdy02; \ + \ + sw_add_vertex_grad_PTCH(&vRight, &dVXdy01); \ + vRight.screen[0] += dXdy01; \ } \ \ - /* Scanline for the lower part of the triangle */ \ - vRight = *v1, vRight.screen[0] = x1; \ + /* Get a copy of next right for interpolation and apply substep correction */ \ + vRight = *v1; \ + sw_add_vertex_grad_scaled_PTCH(&vRight, &dVXdy12, y1Substep); \ + vRight.screen[0] += dXdy12*y1Substep; \ \ - for (int y = yMiddle; y < yBottom; y++) \ + /* Scanline for the lower part of the triangle */ \ + for (int y = yMid; y < yBot; y++) \ { \ vLeft.screen[1] = vRight.screen[1] = y; \ \ - if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, vDy02.texcoord[0], vDy02.texcoord[1]); \ - else FUNC_SCANLINE(tex, &vRight, &vLeft, vDy02.texcoord[0], vDy02.texcoord[1]); \ + if (vLeft.screen[0] < vRight.screen[0]) FUNC_SCANLINE(tex, &vLeft, &vRight, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \ + else FUNC_SCANLINE(tex, &vRight, &vLeft, dVXdy02.texcoord[0], dVXdy02.texcoord[1]); \ \ - sw_add_vertex_grad_PTCH(&vLeft, &vDy02); \ - vLeft.screen[0] += dx02; \ - sw_add_vertex_grad_PTCH(&vRight, &vDy12); \ - vRight.screen[0] += dx12; \ + sw_add_vertex_grad_PTCH(&vLeft, &dVXdy02); \ + vLeft.screen[0] += dXdy02; \ + \ + sw_add_vertex_grad_PTCH(&vRight, &dVXdy12); \ + vRight.screen[0] += dXdy12; \ } \ } @@ -2716,41 +2762,46 @@ static inline void FUNC_NAME(void) const sw_vertex_t *v3 = sortedVerts[3]; \ \ /* Screen bounds (axis-aligned) */ \ - int xMin = (int)(v0->screen[0] + 0.5f); \ - int yMin = (int)(v0->screen[1] + 0.5f); \ - int xMax = (int)(v2->screen[0] + 0.5f); \ - int yMax = (int)(v2->screen[1] + 0.5f); \ + int xMin = (int)v0->screen[0]; \ + int yMin = (int)v0->screen[1]; \ + int xMax = (int)v2->screen[0]; \ + int yMax = (int)v2->screen[1]; \ \ - int width = xMax - xMin; \ - int height = yMax - yMin; \ + float w = v2->screen[0] - v0->screen[0]; \ + float h = v2->screen[1] - v0->screen[1]; \ \ - if ((width == 0) || (height == 0)) return; \ + if ((w == 0) || (h == 0)) return; \ \ - float wRcp = (width > 0.0f)? 1.0f/width : 0.0f; \ - float hRcp = (height > 0.0f)? 1.0f/height : 0.0f; \ + float wRcp = (w > 0.0f)? 1.0f/w : 0.0f; \ + float hRcp = (h > 0.0f)? 1.0f/h : 0.0f; \ + \ + /* Subpixel corrections */ \ + float xSubstep = 1.0f - sw_fract(v0->screen[0]); \ + float ySubstep = 1.0f - sw_fract(v0->screen[1]); \ \ /* Calculation of vertex gradients in X and Y */ \ - float tcDx[2], tcDy[2]; \ + float dUdx, dVdx; \ + float dUdy, dVdy; \ if (ENABLE_TEXTURE) { \ - tcDx[0] = (v1->texcoord[0] - v0->texcoord[0])*wRcp; \ - tcDx[1] = (v1->texcoord[1] - v0->texcoord[1])*wRcp; \ - tcDy[0] = (v3->texcoord[0] - v0->texcoord[0])*hRcp; \ - tcDy[1] = (v3->texcoord[1] - v0->texcoord[1])*hRcp; \ + dUdx = (v1->texcoord[0] - v0->texcoord[0])*wRcp; \ + dVdx = (v1->texcoord[1] - v0->texcoord[1])*wRcp; \ + dUdy = (v3->texcoord[0] - v0->texcoord[0])*hRcp; \ + dVdy = (v3->texcoord[1] - v0->texcoord[1])*hRcp; \ } \ \ - float cDx[4], cDy[4]; \ - cDx[0] = (v1->color[0] - v0->color[0])*wRcp; \ - cDx[1] = (v1->color[1] - v0->color[1])*wRcp; \ - cDx[2] = (v1->color[2] - v0->color[2])*wRcp; \ - cDx[3] = (v1->color[3] - v0->color[3])*wRcp; \ - cDy[0] = (v3->color[0] - v0->color[0])*hRcp; \ - cDy[1] = (v3->color[1] - v0->color[1])*hRcp; \ - cDy[2] = (v3->color[2] - v0->color[2])*hRcp; \ - cDy[3] = (v3->color[3] - v0->color[3])*hRcp; \ + float dCdx[4], dCdy[4]; \ + dCdx[0] = (v1->color[0] - v0->color[0])*wRcp; \ + dCdx[1] = (v1->color[1] - v0->color[1])*wRcp; \ + dCdx[2] = (v1->color[2] - v0->color[2])*wRcp; \ + dCdx[3] = (v1->color[3] - v0->color[3])*wRcp; \ + dCdy[0] = (v3->color[0] - v0->color[0])*hRcp; \ + dCdy[1] = (v3->color[1] - v0->color[1])*hRcp; \ + dCdy[2] = (v3->color[2] - v0->color[2])*hRcp; \ + dCdy[3] = (v3->color[3] - v0->color[3])*hRcp; \ \ - float zDx, zDy; \ - zDx = (v1->homogeneous[2] - v0->homogeneous[2])*wRcp; \ - zDy = (v3->homogeneous[2] - v0->homogeneous[2])*hRcp; \ + float dZdx, dZdy; \ + dZdx = (v1->homogeneous[2] - v0->homogeneous[2])*wRcp; \ + dZdy = (v3->homogeneous[2] - v0->homogeneous[2])*hRcp; \ \ /* Start of quad rasterization */ \ const sw_texture_t *tex; \ @@ -2760,15 +2811,15 @@ static inline void FUNC_NAME(void) void *dDstBase = RLSW.framebuffer.depth; \ int wDst = RLSW.framebuffer.width; \ \ - float zScanline = v0->homogeneous[2]; \ - float uScanline = v0->texcoord[0]; \ - float vScanline = v0->texcoord[1]; \ + float zScanline = v0->homogeneous[2] + dZdx*xSubstep + dZdy*ySubstep; \ + float uScanline = v0->texcoord[0] + dUdx*xSubstep + dUdy*ySubstep; \ + float vScanline = v0->texcoord[1] + dVdx*xSubstep + dVdy*ySubstep; \ \ float colorScanline[4] = { \ - v0->color[0], \ - v0->color[1], \ - v0->color[2], \ - v0->color[3] \ + v0->color[0] + dCdx[0]*xSubstep + dCdy[0]*ySubstep, \ + v0->color[1] + dCdx[1]*xSubstep + dCdy[1]*ySubstep, \ + v0->color[2] + dCdx[2]*xSubstep + dCdy[2]*ySubstep, \ + v0->color[3] + dCdx[3]*xSubstep + dCdy[3]*ySubstep \ }; \ \ for (int y = yMin; y < yMax; y++) \ @@ -2806,12 +2857,13 @@ static inline void FUNC_NAME(void) if (z > depth) goto discard; \ } \ \ + /* TODO: Implement depth mask */ \ sw_framebuffer_write_depth(dptr, z); \ \ if (ENABLE_TEXTURE) \ { \ float texColor[4]; \ - sw_texture_sample(texColor, tex, u, v, tcDx[0], tcDy[0], tcDx[1], tcDy[1]); \ + sw_texture_sample(texColor, tex, u, v, dUdx, dUdy, dVdx, dVdy); \ srcColor[0] *= texColor[0]; \ srcColor[1] *= texColor[1]; \ srcColor[2] *= texColor[2]; \ @@ -2828,32 +2880,32 @@ static inline void FUNC_NAME(void) else sw_framebuffer_write_color(cptr, srcColor); \ \ discard: \ - z += zDx; \ - color[0] += cDx[0]; \ - color[1] += cDx[1]; \ - color[2] += cDx[2]; \ - color[3] += cDx[3]; \ + z += dZdx; \ + color[0] += dCdx[0]; \ + color[1] += dCdx[1]; \ + color[2] += dCdx[2]; \ + color[3] += dCdx[3]; \ \ if (ENABLE_TEXTURE) \ { \ - u += tcDx[0]; \ - v += tcDx[1]; \ + u += dUdx; \ + v += dVdx; \ } \ \ INC_COLOR_PTR(cptr); \ INC_DEPTH_PTR(dptr); \ } \ \ - zScanline += zDy; \ - colorScanline[0] += cDy[0]; \ - colorScanline[1] += cDy[1]; \ - colorScanline[2] += cDy[2]; \ - colorScanline[3] += cDy[3]; \ + zScanline += dZdy; \ + colorScanline[0] += dCdy[0]; \ + colorScanline[1] += dCdy[1]; \ + colorScanline[2] += dCdy[2]; \ + colorScanline[3] += dCdy[3]; \ \ if (ENABLE_TEXTURE) \ { \ - uScanline += tcDy[0]; \ - vScanline += tcDy[1]; \ + uScanline += dUdy; \ + vScanline += dVdy; \ } \ } \ } @@ -3021,137 +3073,87 @@ static inline bool sw_line_clip_and_project(sw_vertex_t *v0, sw_vertex_t *v1) #define DEFINE_LINE_RASTER(FUNC_NAME, ENABLE_DEPTH_TEST, ENABLE_COLOR_BLEND) \ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ { \ - int x1 = (int)(v0->screen[0] + 0.5f); \ - int y1 = (int)(v0->screen[1] + 0.5f); \ - int x2 = (int)(v1->screen[0] + 0.5f); \ - int y2 = (int)(v1->screen[1] + 0.5f); \ + float x0 = v0->screen[0]; \ + float y0 = v0->screen[1]; \ + float x1 = v1->screen[0]; \ + float y1 = v1->screen[1]; \ \ - int dx = x2 - x1; \ - int dy = y2 - y1; \ + float dx = x1 - x0; \ + float dy = y1 - y0; \ \ - /* Handling of lines that are more horizontal or vertical */ \ - if ((dx == 0) && (dy == 0)) \ + /* Compute dominant axis and subpixel offset */ \ + float steps, substep; \ + if (fabsf(dx) > fabsf(dy)) \ { \ - /* TODO: A point should be rendered here */ \ - return; \ - } \ - \ - bool yLonger = (abs(dy) > abs(dx)); \ - int longLen, shortLen; \ - \ - if (yLonger) \ - { \ - longLen = dy; \ - shortLen = dx; \ + steps = fabsf(dx); \ + if (steps < 1.0f) return; \ + substep = (dx >= 0.0f)? (1.0f - sw_fract(x0)) : sw_fract(x0); \ } \ else \ { \ - longLen = dx; \ - shortLen = dy; \ + steps = fabsf(dy); \ + if (steps < 1.0f) return; \ + substep = (dy >= 0.0f)? (1.0f - sw_fract(y0)) : sw_fract(y0); \ } \ \ - /* Handling of traversal direction */ \ - int sgnInc = (longLen < 0)? -1 : 1; \ - int abslongLen = abs(longLen); \ + /* Compute per pixel increments */ \ + float xInc = dx/steps; \ + float yInc = dy/steps; \ + float stepRcp = 1.0f/steps; \ \ - /* Calculation of the increment step for the shorter coordinate */ \ - int decInc = 0; \ - if (abslongLen != 0) decInc = (shortLen << 16)/abslongLen; \ + float zInc = (v1->homogeneous[2] - v0->homogeneous[2])*stepRcp; \ + float rInc = (v1->color[0] - v0->color[0])*stepRcp; \ + float gInc = (v1->color[1] - v0->color[1])*stepRcp; \ + float bInc = (v1->color[2] - v0->color[2])*stepRcp; \ + float aInc = (v1->color[3] - v0->color[3])*stepRcp; \ \ - float longLenRcp = (abslongLen != 0)? (1.0f/abslongLen) : 0.0f; \ - \ - /* Calculation of interpolation steps */ \ - const float zStep = (v1->homogeneous[2] - v0->homogeneous[2])*longLenRcp; \ - const float rStep = (v1->color[0] - v0->color[0])*longLenRcp; \ - const float gStep = (v1->color[1] - v0->color[1])*longLenRcp; \ - const float bStep = (v1->color[2] - v0->color[2])*longLenRcp; \ - const float aStep = (v1->color[3] - v0->color[3])*longLenRcp; \ - \ - float z = v0->homogeneous[2]; \ - \ - float color[4] = { \ - v0->color[0], \ - v0->color[1], \ - v0->color[2], \ - v0->color[3] \ - }; \ + /* Initializing the interpolation starting values */ \ + float x = x0 + xInc*substep; \ + float y = y0 + yInc*substep; \ + float z = v0->homogeneous[2] + zInc*substep; \ + float r = v0->color[0] + rInc*substep; \ + float g = v0->color[1] + gInc*substep; \ + float b = v0->color[2] + bInc*substep; \ + float a = v0->color[3] + aInc*substep; \ \ const int fbWidth = RLSW.framebuffer.width; \ void *cBuffer = RLSW.framebuffer.color; \ void *dBuffer = RLSW.framebuffer.depth; \ \ - int j = 0; \ - if (yLonger) \ + int numPixels = (int)(steps - substep) + 1; \ + \ + for (int i = 0; i < numPixels; i++) \ { \ - for (int i = 0; i != longLen; i += sgnInc) \ + /* REVIEW: May require reviewing projection details */ \ + int px = (int)(x - 0.5f); \ + int py = (int)(y - 0.5f); \ + \ + int offset = py*fbWidth + px; \ + void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ + \ + if (ENABLE_DEPTH_TEST) \ { \ - int offset = (y1 + i)*fbWidth + (x1 + (j >> 16)); \ - void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ - void *cptr = NULL; \ - \ - if (ENABLE_DEPTH_TEST) \ - { \ - float depth = sw_framebuffer_read_depth(dptr); \ - if (z > depth) goto discardA; \ - } \ - \ - sw_framebuffer_write_depth(dptr, z); \ - \ - cptr = GET_COLOR_PTR(cBuffer, offset); \ - \ - if (ENABLE_COLOR_BLEND) \ - { \ - float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ - sw_blend_colors(dstColor, color); \ - sw_framebuffer_write_color(cptr, dstColor); \ - } \ - else sw_framebuffer_write_color(cptr, color); \ - \ - discardA: \ - j += decInc; \ - z += zStep; \ - color[0] += rStep; \ - color[1] += gStep; \ - color[2] += bStep; \ - color[3] += aStep; \ + float depth = sw_framebuffer_read_depth(dptr); \ + if (z > depth) goto discard; \ } \ - } \ - else \ - { \ - for (int i = 0; i != longLen; i += sgnInc) \ + \ + sw_framebuffer_write_depth(dptr, z); \ + \ + void *cptr = GET_COLOR_PTR(cBuffer, offset); \ + float color[4] = {r, g, b, a}; \ + \ + if (ENABLE_COLOR_BLEND) \ { \ - int offset = (y1 + (j >> 16))*fbWidth + (x1 + i); \ - void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ - void *cptr = NULL; \ - \ - if (ENABLE_DEPTH_TEST) \ - { \ - float depth = sw_framebuffer_read_depth(dptr); \ - if (z > depth) goto discardB; \ - } \ - \ - sw_framebuffer_write_depth(dptr, z); \ - \ - cptr = GET_COLOR_PTR(cBuffer, offset); \ - \ - if (ENABLE_COLOR_BLEND) \ - { \ - float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ - sw_blend_colors(dstColor, color); \ - sw_framebuffer_write_color(cptr, dstColor); \ - } \ - else sw_framebuffer_write_color(cptr, color); \ - \ - discardB: \ - j += decInc; \ - z += zStep; \ - color[0] += rStep; \ - color[1] += gStep; \ - color[2] += bStep; \ - color[3] += aStep; \ + float dstColor[4]; \ + sw_framebuffer_read_color(dstColor, cptr); \ + sw_blend_colors(dstColor, color); \ + sw_framebuffer_write_color(cptr, dstColor); \ } \ + else sw_framebuffer_write_color(cptr, color); \ + \ + discard: \ + x += xInc; y += yInc; z += zInc; \ + r += rInc; g += gInc; b += bInc; a += aInc; \ } \ } @@ -3857,11 +3859,11 @@ void swViewport(int x, int y, int width, int height) RLSW.vpSize[0] = width; RLSW.vpSize[1] = height; - RLSW.vpHalfSize[0] = (int)(width/2.0f + 0.5f); - RLSW.vpHalfSize[1] = (int)(height/2.0f + 0.5f); + RLSW.vpHalf[0] = width/2.0f; + RLSW.vpHalf[1] = height/2.0f; - RLSW.vpCenter[0] = x + RLSW.vpHalfSize[0]; - RLSW.vpCenter[1] = y + RLSW.vpHalfSize[1]; + RLSW.vpCenter[0] = (float)x + RLSW.vpHalf[0]; + RLSW.vpCenter[1] = (float)y + RLSW.vpHalf[1]; RLSW.vpMin[0] = sw_clampi(x, 0, RLSW.framebuffer.width - 1); RLSW.vpMin[1] = sw_clampi(y, 0, RLSW.framebuffer.height - 1); From 1c20b5588d349c08a0e0df114477e5f4090f6966 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 25 Oct 2025 23:20:49 +0200 Subject: [PATCH 072/102] Updatee project id --- .../shapes_math_angle_rotation.vcxproj | 2 +- projects/VS2022/raylib.sln | 27 ++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj b/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj index 0bee76192..48da9d846 100644 --- a/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj +++ b/projects/VS2022/examples/shapes_math_angle_rotation.vcxproj @@ -51,7 +51,7 @@ - {6B1A933E-71B8-4C1F-9E79-02D98830E671} + {84DE22BB-C25F-425C-A7FE-0120CF107B83} Win32Proj shapes_math_angle_rotation 10.0 diff --git a/projects/VS2022/raylib.sln b/projects/VS2022/raylib.sln index 8d2704abf..81f700bec 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -395,7 +395,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core_text_file_loading", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_mandelbrot_set", "examples\shaders_mandelbrot_set.vcxproj", "{1C829D1A-892C-451C-AF0B-AC65C85F5CC6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_angle_rotation", "examples\shapes_math_angle_rotation.vcxproj", "{6B1A933E-71B8-4C1F-9E79-02D98830E671}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_angle_rotation", "examples\shapes_math_angle_rotation.vcxproj", "{84DE22BB-C25F-425C-A7FE-0120CF107B83}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -4899,6 +4899,30 @@ Global {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x64.Build.0 = Release|x64 {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x86.ActiveCfg = Release|Win32 {1C829D1A-892C-451C-AF0B-AC65C85F5CC6}.Release|x86.Build.0 = Release|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|ARM64.Build.0 = Debug|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|x64.ActiveCfg = Debug|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|x64.Build.0 = Debug|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|x86.ActiveCfg = Debug|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Debug|x86.Build.0 = Debug|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|ARM64.ActiveCfg = Release|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|ARM64.Build.0 = Release|ARM64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x64.ActiveCfg = Release|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x64.Build.0 = Release|x64 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x86.ActiveCfg = Release|Win32 + {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5098,6 +5122,7 @@ Global {9DE2FC01-A839-4F89-8319-9071D4C54821} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {2F578155-D51F-4C03-AB7F-5C5122CA46CC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {1C829D1A-892C-451C-AF0B-AC65C85F5CC6} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} + {84DE22BB-C25F-425C-A7FE-0120CF107B83} = {278D8859-20B1-428F-8448-064F46E1F021} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From a818508158119f74e99b4dc98345c28ce112733c Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Sun, 26 Oct 2025 00:58:56 +0200 Subject: [PATCH 073/102] [rlsw] Completeness of `glDraw` functions (#5304) * adding `glDrawElements` * tweaks * fix `glDrawArrays` and `glDrawElements` behavior --- src/external/rlsw.h | 303 +++++++++++++++++++++++++++++++++----------- 1 file changed, 229 insertions(+), 74 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 50a60d74f..e049e707e 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -376,6 +376,7 @@ typedef double GLclampd; #define glTexCoordPointer(sz, t, s, p) swBindArray(SW_TEXTURE_COORD_ARRAY, (p)) #define glColorPointer(sz, t, s, p) swBindArray(SW_COLOR_ARRAY, (p)) #define glDrawArrays(m, o, c) swDrawArrays((m), (o), (c)) +#define glDrawElements(m,c,t,i) swDrawElements((m),(c),(t),(i)) #define glGenTextures(c, v) swGenTextures((c), (v)) #define glDeleteTextures(c, v) swDeleteTextures((c), (v)) #define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p)) @@ -393,7 +394,6 @@ typedef double GLclampd; #define glDepthFunc(X) ((void)(X)) #define glTexSubImage2D(X,Y,Z,W,A,B,C,D,E) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A),(void)(B),(void)(C),(void)(D),(void)(E)) #define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A)) -#define glDrawElements(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W)) #define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z)) #define glNormal3fv(X) ((void)(X)) #define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z)) @@ -589,6 +589,7 @@ SWAPI void swTexCoord2fv(const float *v); SWAPI void swBindArray(SWarray type, void *buffer); SWAPI void swDrawArrays(SWdraw mode, int offset, int count); +SWAPI void swDrawElements(SWdraw mode, int count, int type, const void *indices); SWAPI void swGenTextures(int count, uint32_t *textures); SWAPI void swDeleteTextures(int count, uint32_t *textures); @@ -674,6 +675,7 @@ SWAPI void swBindTexture(uint32_t id); // Defines and Macros //---------------------------------------------------------------------------------- #define SW_PI 3.14159265358979323846f +#define SW_INV_255 0.00392156862745098f #define SW_DEG2RAD (SW_PI/180.0f) #define SW_RAD2DEG (180.0f/SW_PI) @@ -1120,26 +1122,26 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16)); float32x4_t floats = vcvtq_f32_u32(ints); - floats = vmulq_n_f32(floats, 1.0f/255.0f); + floats = vmulq_n_f32(floats, SW_INV_255); vst1q_f32(dst, floats); #elif defined(SW_HAS_SSE41) __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); __m128i ints = _mm_cvtepu8_epi32(bytes); __m128 floats = _mm_cvtepi32_ps(ints); - floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); + floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255)); _mm_storeu_ps(dst, floats); #elif defined(SW_HAS_SSE2) __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128()); __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128()); __m128 floats = _mm_cvtepi32_ps(ints); - floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); + floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255)); _mm_storeu_ps(dst, floats); #else - dst[0] = (float)src[0]/255.0f; - dst[1] = (float)src[1]/255.0f; - dst[2] = (float)src[2]/255.0f; - dst[3] = (float)src[3]/255.0f; + dst[0] = (float)src[0]*SW_INV_255; + dst[1] = (float)src[1]*SW_INV_255; + dst[2] = (float)src[2]*SW_INV_255; + dst[3] = (float)src[3]*SW_INV_255; #endif } @@ -1894,7 +1896,7 @@ static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t off case SW_PIXELFORMAT_UNCOMPRESSED_R16: { uint16_t val = ((const uint16_t*)pixels)[offset]; - uint8_t gray = sw_half_to_float(val)/255.0f; + uint8_t gray = sw_half_to_float(val)*SW_INV_255; color[0] = gray; color[1] = gray; color[2] = gray; @@ -1904,19 +1906,19 @@ static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t off case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: { const uint16_t *src = &((const uint16_t*)pixels)[offset*3]; - color[0] = sw_half_to_float(src[0])/255.0f; - color[1] = sw_half_to_float(src[1])/255.0f; - color[2] = sw_half_to_float(src[2])/255.0f; + color[0] = sw_half_to_float(src[0])*SW_INV_255; + color[1] = sw_half_to_float(src[1])*SW_INV_255; + color[2] = sw_half_to_float(src[2])*SW_INV_255; color[3] = 255; break; } case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: { const uint16_t *src = &((const uint16_t*)pixels)[offset*4]; - color[0] = sw_half_to_float(src[0])/255.0f; - color[1] = sw_half_to_float(src[1])/255.0f; - color[2] = sw_half_to_float(src[2])/255.0f; - color[3] = sw_half_to_float(src[3])/255.0f; + color[0] = sw_half_to_float(src[0])*SW_INV_255; + color[1] = sw_half_to_float(src[1])*SW_INV_255; + color[2] = sw_half_to_float(src[2])*SW_INV_255; + color[3] = sw_half_to_float(src[3])*SW_INV_255; break; } case SW_PIXELFORMAT_UNKNOWN: @@ -3404,7 +3406,7 @@ static inline void sw_point_render(sw_vertex_t *v) } //------------------------------------------------------------------------------------------- -// Polygon modes mendering logic +// Polygon modes rendering logic //------------------------------------------------------------------------------------------- static inline void sw_poly_point_render(void) { @@ -3436,9 +3438,47 @@ static inline void sw_poly_fill_render(void) case SW_QUADS: sw_quad_render(); break; } } +//------------------------------------------------------------------------------------------- + +// Immediate rendering logic +//------------------------------------------------------------------------------------------- +void sw_immediate_push_vertex(const float position[4], const float color[4], const float texcoord[2]) +{ + // Copy the attributes in the current vertex + sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++]; + for (int i = 0; i < 4; i++) + { + vertex->position[i] = position[i]; + if (i < 2) vertex->texcoord[i] = texcoord[i]; + vertex->color[i] = color[i]; + } + + // Calculate homogeneous coordinates + const float *m = RLSW.matMVP, *v = vertex->position; + vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3]; + vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3]; + vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; + vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; + + // Immediate rendering of the primitive if the required number is reached + if (RLSW.vertexCounter == RLSW.reqVertices) + { + switch (RLSW.polyMode) + { + case SW_FILL: sw_poly_fill_render(); break; + case SW_LINE: sw_poly_line_render(); break; + case SW_POINT: sw_poly_point_render(); break; + default: break; + } + + RLSW.vertexCounter = 0; + } +} + +//------------------------------------------------------------------------------------------- // Validity check helper functions - +//------------------------------------------------------------------------------------------- static inline bool sw_is_texture_valid(uint32_t id) { bool valid = true; @@ -4301,89 +4341,62 @@ void swEnd(void) void swVertex2i(int x, int y) { const float v[4] = { (float)x, (float)y, 0.0f, 1.0f }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex2f(float x, float y) { const float v[4] = { x, y, 0.0f, 1.0f }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex2fv(const float *v) { const float v4[4] = { v[0], v[1], 0.0f, 1.0f }; - swVertex4fv(v4); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex3i(int x, int y, int z) { const float v[4] = { (float)x, (float)y, (float)z, 1.0f }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex3f(float x, float y, float z) { const float v[4] = { x, y, z, 1.0f }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex3fv(const float *v) { const float v4[4] = { v[0], v[1], v[2], 1.0f }; - swVertex4fv(v4); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex4i(int x, int y, int z, int w) { const float v[4] = { (float)x, (float)y, (float)z, (float)w }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex4f(float x, float y, float z, float w) { const float v[4] = { x, y, z, w }; - swVertex4fv(v); + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swVertex4fv(const float *v) { - // Copy the position in the current vertex - sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++]; - for (int i = 0; i < 4; i++) vertex->position[i] = v[i]; - - // Copy additonal vertex data - for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.current.texcoord[i]; - for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.current.color[i]; - - // Calculation of homogeneous coordinates - const float *m = RLSW.matMVP; - vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3]; - vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3]; - vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3]; - vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3]; - - // Immediate rendering of the primitive if the required number is reached - if (RLSW.vertexCounter == RLSW.reqVertices) - { - switch (RLSW.polyMode) - { - case SW_FILL: sw_poly_fill_render(); break; - case SW_LINE: sw_poly_line_render(); break; - case SW_POINT: sw_poly_point_render(); break; - default: break; - } - - RLSW.vertexCounter = 0; - } + sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord); } void swColor3ub(uint8_t r, uint8_t g, uint8_t b) { float cv[4]; - cv[0] = (float)r/255; - cv[1] = (float)g/255; - cv[2] = (float)b/255; + cv[0] = (float)r*SW_INV_255; + cv[1] = (float)g*SW_INV_255; + cv[2] = (float)b*SW_INV_255; cv[3] = 1.0f; swColor4fv(cv); @@ -4392,9 +4405,9 @@ void swColor3ub(uint8_t r, uint8_t g, uint8_t b) void swColor3ubv(const uint8_t *v) { float cv[4]; - cv[0] = (float)v[0]/255; - cv[1] = (float)v[1]/255; - cv[2] = (float)v[2]/255; + cv[0] = (float)v[0]*SW_INV_255; + cv[1] = (float)v[1]*SW_INV_255; + cv[2] = (float)v[2]*SW_INV_255; cv[3] = 1.0f; swColor4fv(cv); @@ -4425,10 +4438,10 @@ void swColor3fv(const float *v) void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a) { float cv[4]; - cv[0] = (float)r/255; - cv[1] = (float)g/255; - cv[2] = (float)b/255; - cv[3] = (float)a/255; + cv[0] = (float)r*SW_INV_255; + cv[1] = (float)g*SW_INV_255; + cv[2] = (float)b*SW_INV_255; + cv[3] = (float)a*SW_INV_255; swColor4fv(cv); } @@ -4436,10 +4449,10 @@ void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a) void swColor4ubv(const uint8_t *v) { float cv[4]; - cv[0] = (float)v[0]/255; - cv[1] = (float)v[1]/255; - cv[2] = (float)v[2]/255; - cv[3] = (float)v[3]/255; + cv[0] = (float)v[0]*SW_INV_255; + cv[1] = (float)v[1]*SW_INV_255; + cv[2] = (float)v[2]*SW_INV_255; + cv[3] = (float)v[3]*SW_INV_255; swColor4fv(cv); } @@ -4497,14 +4510,156 @@ void swDrawArrays(SWdraw mode, int offset, int count) swBegin(mode); { - swTexCoord2f(0.0f, 0.0f); - swColor4f(1.0f, 1.0f, 1.0f, 1.0f); + const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1]; + const float *defaultTexcoord = RLSW.current.texcoord; + const float *defaultColor = RLSW.current.color; + + const float *positions = RLSW.array.positions; + const float *texcoords = RLSW.array.texcoords; + const uint8_t *colors = RLSW.array.colors; - for (int i = offset; i < count; i++) + int end = offset + count; + + for (int i = offset; i < end; i++) { - if (RLSW.array.texcoords) swTexCoord2fv(RLSW.array.texcoords + 2*i); - if (RLSW.array.colors) swColor4ubv(RLSW.array.colors + 4*i); - swVertex3fv(RLSW.array.positions + 3*i); + float u, v; + if (texcoords) + { + int idx = 2 * i; + u = texcoords[idx]; + v = texcoords[idx + 1]; + } + else + { + u = defaultTexcoord[0]; + v = defaultTexcoord[1]; + } + + float texcoord[2]; + texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12]; + texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13]; + + float color[4] = { + defaultColor[0], + defaultColor[1], + defaultColor[2], + defaultColor[3] + }; + + if (colors) + { + int idx = 4 * i; + color[0] *= (float)colors[idx]*SW_INV_255; + color[1] *= (float)colors[idx + 1]*SW_INV_255; + color[2] *= (float)colors[idx + 2]*SW_INV_255; + color[3] *= (float)colors[idx + 3]*SW_INV_255; + } + + int idx = 3 * i; + float position[4] = { + positions[idx], + positions[idx + 1], + positions[idx + 2], + 1.0f + }; + + sw_immediate_push_vertex(position, color, texcoord); + } + } + swEnd(); +} + +void swDrawElements(SWdraw mode, int count, int type, const void *indices) +{ + if (RLSW.array.positions == 0) + { + RLSW.errCode = SW_INVALID_OPERATION; + return; + } + + if (count < 0) + { + RLSW.errCode = SW_INVALID_VALUE; + return; + } + + const uint8_t *indicesUb = NULL; + const uint16_t *indicesUs = NULL; + const uint32_t *indicesUi = NULL; + + switch (type) + { + case SW_UNSIGNED_BYTE: + indicesUb = (const uint8_t *)indices; + break; + case SW_UNSIGNED_SHORT: + indicesUs = (const uint16_t *)indices; + break; + case SW_UNSIGNED_INT: + indicesUi = (const uint32_t *)indices; + break; + default: + RLSW.errCode = SW_INVALID_ENUM; + return; + } + + swBegin(mode); + { + const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1]; + const float *defaultTexcoord = RLSW.current.texcoord; + const float *defaultColor = RLSW.current.color; + + const float *positions = RLSW.array.positions; + const float *texcoords = RLSW.array.texcoords; + const uint8_t *colors = RLSW.array.colors; + + for (int i = 0; i < count; i++) + { + int index = indicesUb ? indicesUb[i] : + (indicesUs ? indicesUs[i] : indicesUi[i]); + + float u, v; + if (texcoords) + { + int idx = 2 * index; + u = texcoords[idx]; + v = texcoords[idx + 1]; + } + else + { + u = defaultTexcoord[0]; + v = defaultTexcoord[1]; + } + + float texcoord[2]; + texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12]; + texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13]; + + float color[4] = { + defaultColor[0], + defaultColor[1], + defaultColor[2], + defaultColor[3] + }; + + if (colors) + { + int idx = 4 * index; + color[0] *= (float)colors[idx]*SW_INV_255; + color[1] *= (float)colors[idx + 1]*SW_INV_255; + color[2] *= (float)colors[idx + 2]*SW_INV_255; + color[3] *= (float)colors[idx + 3]*SW_INV_255; + } + + int idx = 3 * index; + float position[4] = { + positions[idx], + positions[idx + 1], + positions[idx + 2], + 1.0f + }; + + sw_immediate_push_vertex(position, color, texcoord); } } swEnd(); From e244cf297abd7c3cac887cbb38ad194d4c20a53d Mon Sep 17 00:00:00 2001 From: themushroompirates <59015901+themushroompirates@users.noreply.github.com> Date: Sun, 26 Oct 2025 18:15:45 +0100 Subject: [PATCH 074/102] examples_model_decals : Fixed unload crash, added buttons (#5306) --- examples/models/models_decals.c | 497 +++++++++++++++++------------- examples/models/models_decals.png | Bin 62387 -> 67453 bytes 2 files changed, 283 insertions(+), 214 deletions(-) diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index af1ecfc6d..2786168f6 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -43,8 +43,10 @@ typedef struct MeshBuilder { static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]); static void FreeMeshBuilder(MeshBuilder *mb); static Mesh BuildMesh(MeshBuilder *mb); -static Mesh GenMeshDecal(Mesh inputMesh, Ray ray); +static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset); static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); +#define FreeDecalMeshData() GenMeshDecal((Model){ .meshCount = -1.0f }, (Matrix){ 0 }, 0.0f, 0.0f) +static bool Button(Rectangle rec, char *label); //------------------------------------------------------------------------------------ // Program main entry point @@ -105,10 +107,6 @@ int main(void) decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture; decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE; - // We're going to use these to build up our decal meshes - // They'll resize automatically as we go, we'll free them at the end - MeshBuilder meshBuilders[2] = { 0 }; - bool showModel = true; Model decalModels[MAX_DECALS] = { 0 }; int decalCount = 0; @@ -123,8 +121,6 @@ int main(void) //---------------------------------------------------------------------------------- if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) UpdateCamera(&camera, CAMERA_THIRD_PERSON); - if (IsKeyPressed(KEY_SPACE)) showModel = !showModel; - // Display information about closest hit RayCollision collision = { 0 }; collision.distance = FLT_MAX; @@ -165,206 +161,12 @@ int main(void) // Spin the placement around a bit splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*((float)GetRandomValue(-180, 180)))); - Matrix splatInv = MatrixInvert(splat); - // Reset the mesh builders - meshBuilders[0].vertexCount = 0; - meshBuilders[1].vertexCount = 0; - - // We'll be flip-flopping between the two mesh builders - // Reading from one and writing to the other, then swapping - int mbIndex = 0; - - // First pass, just get any triangle inside the bounding box (for each mesh of the model) - for (int meshIndex = 0; meshIndex < model.meshCount; meshIndex++) - { - Mesh mesh = model.meshes[meshIndex]; - for (int tri = 0; tri < mesh.triangleCount; tri++) - { - Vector3 vertices[3] = { 0 }; - - // The way we calculate the vertices of the mesh triangle - // depend on whether the mesh vertices are indexed or not - if (mesh.indices == 0) - { - for (int v = 0; v < 3; v++) - { - vertices[v] = (Vector3){ - mesh.vertices[3*3*tri + 3*v + 0], - mesh.vertices[3*3*tri + 3*v + 1], - mesh.vertices[3*3*tri + 3*v + 2] - }; - } - } - else - { - for (int v = 0; v < 3; v++) - { - vertices[v] = (Vector3){ - mesh.vertices[ 3*mesh.indices[3*tri+0] + v], - mesh.vertices[ 3*mesh.indices[3*tri+1] + v], - mesh.vertices[ 3*mesh.indices[3*tri+2] + v] - }; - } - } - - // Transform all 3 vertices of the triangle - // and check if they are inside our decal box - int insideCount = 0; - for (int i = 0; i < 3; i++) - { - // To splat space - Vector3 v = Vector3Transform(vertices[i], splat); - - if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++; - - // We need to keep the transformed vertex - vertices[i] = v; - } - - // If any of them are inside, we add the triangle - we'll clip it later - if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices); - } - } - - // Clipping time! We need to clip against all 6 directions - Vector3 planes[6] = { - { 1, 0, 0 }, - { -1, 0, 0 }, - { 0, 1, 0 }, - { 0, -1, 0 }, - { 0, 0, 1 }, - { 0, 0, -1 } - }; - - for (int face = 0; face < 6; face++) - { - // Swap current model builder (so we read from the one we just wrote to) - mbIndex = 1 - mbIndex; - - MeshBuilder *inMesh = &meshBuilders[1 - mbIndex]; - MeshBuilder *outMesh = &meshBuilders[mbIndex]; - - // Reset write builder - outMesh->vertexCount = 0; - - float s = 0.5f*decalSize; - - for (int i = 0; i < inMesh->vertexCount; i += 3) - { - Vector3 nV1, nV2, nV3, nV4; - - float d1 = Vector3DotProduct(inMesh->vertices[ i + 0 ], planes[face] ) - s; - float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s; - float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s; - - int v1Out = (d1 > 0); - int v2Out = (d2 > 0); - int v3Out = (d3 > 0); - - // Calculate, how many vertices of the face lie outside of the clipping plane - int total = v1Out + v2Out + v3Out; - - switch (total) - { - case 0: - { - // The entire face lies inside of the plane, no clipping needed - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]}); - } break; - case 1: - { - // One vertex lies outside of the plane, perform clipping - if (v1Out) - { - nV1 = inMesh->vertices[i + 1]; - nV2 = inMesh->vertices[i + 2]; - nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s); - nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s); - } - - if (v2Out) - { - nV1 = inMesh->vertices[i]; - nV2 = inMesh->vertices[i + 2]; - nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s); - nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s); - - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1}); - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4}); - break; - } - - if (v3Out) - { - nV1 = inMesh->vertices[i]; - nV2 = inMesh->vertices[i + 1]; - nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s); - nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s); - } - - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2}); - } break; - case 2: - { - // Two vertices lies outside of the plane, perform clipping - if (!v1Out) - { - nV1 = inMesh->vertices[i]; - nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); - nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); - } - - if (!v2Out) - { - nV1 = inMesh->vertices[i + 1]; - nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); - nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); - } - - if (!v3Out) - { - nV1 = inMesh->vertices[i + 2]; - nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); - nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); - AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); - } - } break; - case 3: // The entire face lies outside of the plane, so let's discard the corresponding vertices - default: break; - } - } - } - - // Now we just need to re-transform the vertices - MeshBuilder *theMesh = &meshBuilders[mbIndex]; - - // Allocate room for UVs - if (theMesh->vertexCount > 0) - { - theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); - - for (int i = 0; i < theMesh->vertexCount; i++) - { - // Calculate the UVs based on the projected coords - // They are clipped to (-decalSize .. decalSize) and we want them (0..1) - theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f); - theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f); - - // From splat space to world space - theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], splatInv); - - // Tiny nudge in the normal direction so it renders properly over the mesh - theMesh->vertices[i] = Vector3Add(theMesh->vertices[i], Vector3Scale(collision.normal, decalOffset)); - } - - // Decal model data ready, create it and add it + Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset); + if (decalMesh.vertexCount > 0) { int decalIndex = decalCount++; - decalModels[decalIndex] = LoadModelFromMesh(BuildMesh(theMesh)); - decalModels[decalIndex].materials[0] = decalMaterial; + decalModels[decalIndex] = LoadModelFromMesh(decalMesh); + decalModels[decalIndex].materials[0].maps[0] = decalMaterial.maps[0]; } } //---------------------------------------------------------------------------------- @@ -381,7 +183,7 @@ int main(void) // Draw the decal models for (int i = 0; i < decalCount; i++) DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE); - // If we hit the mesh, draw the box for the decal + // If we hit the mesh, draw the box for the decal if (collision.hit) { Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); @@ -418,13 +220,20 @@ int main(void) for (int i = 0; i < decalCount; i++) { - DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); - DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); - DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); + if (i == 20) { + DrawText("...", x0, yPos, 10, LIME); + yPos += 15; + } + + if (i < 20) { + DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); + DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); + yPos += 15; + } vertexCount += decalModels[i].meshes[0].vertexCount; triangleCount += decalModels[i].meshes[0].triangleCount; - yPos += 15; } DrawText("TOTAL", x0, yPos, 10, LIME); @@ -434,6 +243,23 @@ int main(void) DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); + + Rectangle rect = (Rectangle){ 10, screenHeight - 100, 100, 60 }; + + if (Button(rect, showModel ? "Hide Model" : "Show Model")) { + showModel = !showModel; + } + + rect.x += rect.width + 10; + + if (Button(rect, "Clear Decals")) { + for (int i = 0; i < decalCount; i++) + { + UnloadModel(decalModels[i]); + } + decalCount = 0; + } + DrawFPS(10, 10); @@ -446,13 +272,14 @@ int main(void) UnloadModel(model); UnloadTexture(modelTexture); - // TODO: WARNING: This line crashes program on closing - //for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); + for (int i = 0; i < decalCount; i++) { + UnloadModel(decalModels[i]); + } UnloadTexture(decalTexture); - FreeMeshBuilder(&meshBuilders[0]); - FreeMeshBuilder(&meshBuilders[1]); + // Free the data for decal generation + FreeDecalMeshData(); CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- @@ -536,3 +363,245 @@ static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) return position; } + +static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset) +{ + // We're going to use these to build up our decal meshes + // They'll resize automatically as we go, we'll free them at the end + static MeshBuilder meshBuilders[2] = { 0 }; + + // Ugly way of telling us to free the static MeshBuilder data + if (inputModel.meshCount == -1) { + FreeMeshBuilder(&meshBuilders[0]); + FreeMeshBuilder(&meshBuilders[1]); + return (Mesh){0}; + } + + // We're going to need the inverse matrix + Matrix invProj = MatrixInvert(projection); + + // Reset the mesh builders + meshBuilders[0].vertexCount = 0; + meshBuilders[1].vertexCount = 0; + + // We'll be flip-flopping between the two mesh builders + // Reading from one and writing to the other, then swapping + int mbIndex = 0; + + // First pass, just get any triangle inside the bounding box (for each mesh of the model) + for (int meshIndex = 0; meshIndex < inputModel.meshCount; meshIndex++) + { + Mesh mesh = inputModel.meshes[meshIndex]; + for (int tri = 0; tri < mesh.triangleCount; tri++) + { + Vector3 vertices[3] = { 0 }; + + // The way we calculate the vertices of the mesh triangle + // depend on whether the mesh vertices are indexed or not + if (mesh.indices == 0) + { + for (int v = 0; v < 3; v++) + { + vertices[v] = (Vector3){ + mesh.vertices[3*3*tri + 3*v + 0], + mesh.vertices[3*3*tri + 3*v + 1], + mesh.vertices[3*3*tri + 3*v + 2] + }; + } + } + else + { + for (int v = 0; v < 3; v++) + { + vertices[v] = (Vector3){ + mesh.vertices[ 3*mesh.indices[3*tri+0] + v], + mesh.vertices[ 3*mesh.indices[3*tri+1] + v], + mesh.vertices[ 3*mesh.indices[3*tri+2] + v] + }; + } + } + + // Transform all 3 vertices of the triangle + // and check if they are inside our decal box + int insideCount = 0; + for (int i = 0; i < 3; i++) + { + // To projection space + Vector3 v = Vector3Transform(vertices[i], projection); + + if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++; + + // We need to keep the transformed vertex + vertices[i] = v; + } + + // If any of them are inside, we add the triangle - we'll clip it later + if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices); + } + } + + // Clipping time! We need to clip against all 6 directions + Vector3 planes[6] = { + { 1, 0, 0 }, + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 0, 0, 1 }, + { 0, 0, -1 } + }; + + for (int face = 0; face < 6; face++) + { + // Swap current model builder (so we read from the one we just wrote to) + mbIndex = 1 - mbIndex; + + MeshBuilder *inMesh = &meshBuilders[1 - mbIndex]; + MeshBuilder *outMesh = &meshBuilders[mbIndex]; + + // Reset write builder + outMesh->vertexCount = 0; + + float s = 0.5f*decalSize; + + for (int i = 0; i < inMesh->vertexCount; i += 3) + { + Vector3 nV1, nV2, nV3, nV4; + + float d1 = Vector3DotProduct(inMesh->vertices[ i + 0 ], planes[face] ) - s; + float d2 = Vector3DotProduct(inMesh->vertices[ i + 1 ], planes[face] ) - s; + float d3 = Vector3DotProduct(inMesh->vertices[ i + 2 ], planes[face] ) - s; + + int v1Out = (d1 > 0); + int v2Out = (d2 > 0); + int v3Out = (d3 > 0); + + // Calculate, how many vertices of the face lie outside of the clipping plane + int total = v1Out + v2Out + v3Out; + + switch (total) + { + case 0: + { + // The entire face lies inside of the plane, no clipping needed + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){inMesh->vertices[i], inMesh->vertices[i+1], inMesh->vertices[i+2]}); + } break; + case 1: + { + // One vertex lies outside of the plane, perform clipping + if (v1Out) + { + nV1 = inMesh->vertices[i + 1]; + nV2 = inMesh->vertices[i + 2]; + nV3 = ClipSegment(inMesh->vertices[i], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i], nV2, planes[face], s); + } + + if (v2Out) + { + nV1 = inMesh->vertices[i]; + nV2 = inMesh->vertices[i + 2]; + nV3 = ClipSegment(inMesh->vertices[i + 1], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i + 1], nV2, planes[face], s); + + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV3, nV2, nV1}); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV2, nV3, nV4}); + break; + } + + if (v3Out) + { + nV1 = inMesh->vertices[i]; + nV2 = inMesh->vertices[i + 1]; + nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s); + nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s); + } + + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2}); + } break; + case 2: + { + // Two vertices lies outside of the plane, perform clipping + if (!v1Out) + { + nV1 = inMesh->vertices[i]; + nV2 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + + if (!v2Out) + { + nV1 = inMesh->vertices[i + 1]; + nV2 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + + if (!v3Out) + { + nV1 = inMesh->vertices[i + 2]; + nV2 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); + nV3 = ClipSegment(nV1, inMesh->vertices[i + 1], planes[face], s); + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); + } + } break; + case 3: // The entire face lies outside of the plane, so let's discard the corresponding vertices + default: break; + } + } + } + + // Now we just need to re-transform the vertices + MeshBuilder *theMesh = &meshBuilders[mbIndex]; + + // Allocate room for UVs + if (theMesh->vertexCount > 0) + { + theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); + + for (int i = 0; i < theMesh->vertexCount; i++) + { + // Calculate the UVs based on the projected coords + // They are clipped to (-decalSize .. decalSize) and we want them (0..1) + theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f); + theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f); + + // Tiny nudge in the normal direction so it renders properly over the mesh + theMesh->vertices[i].z -= decalOffset; + + // From projection space to world space + theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], invProj); + } + + // Decal model data ready, create the mesh and return it + return BuildMesh(theMesh); + } + else + { + // Return a blank mesh as there's nothing to add + return (Mesh){ 0 }; + } +} + +static bool Button(Rectangle rec, char *label) +{ + Color bgColor = GRAY; + bool pressed = false; + if (CheckCollisionPointRec(GetMousePosition(), rec)) { + bgColor = LIGHTGRAY; + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + pressed = true; + } + } + + DrawRectangleRec(rec, bgColor); + DrawRectangleLinesEx(rec, 2.0f, DARKGRAY); + + float fontSize = 10.0f; + float textWidth = MeasureText(label, fontSize); + + DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY); + + return pressed; +} \ No newline at end of file diff --git a/examples/models/models_decals.png b/examples/models/models_decals.png index 48e027fe2d1711237f457995d46ddcc0647a102e..6bdbaf17ca034c1e481e5afa69c9f954693dd79e 100644 GIT binary patch literal 67453 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 V(=>jESquye44$rjF6*2UngD6y9?k#& literal 62387 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 z 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

AIX)i);+Q2;^({W#g{?F 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 Date: Sun, 26 Oct 2025 18:21:24 +0100 Subject: [PATCH 075/102] Review formating #5306 --- examples/models/models_decals.c | 172 ++++++++++++++++---------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index 2786168f6..6fa2bd75b 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -71,46 +71,46 @@ int main(void) // Load character model Model model = LoadModel("resources/models/obj/character.obj"); - + // Apply character skin Texture2D modelTexture = LoadTexture("resources/models/obj/character_diffuse.png"); SetTextureFilter(modelTexture, TEXTURE_FILTER_BILINEAR); model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = modelTexture; - + BoundingBox modelBBox = GetMeshBoundingBox(model.meshes[0]); // Get mesh bounding box - + camera.target = Vector3Lerp(modelBBox.min, modelBBox.max, 0.5f); camera.position = Vector3Scale(modelBBox.max, 1.0f); camera.position.x *= 0.1f; - + float modelSize = fminf( fminf(fabsf(modelBBox.max.x - modelBBox.min.x), fabsf(modelBBox.max.y - modelBBox.min.y)), fabsf(modelBBox.max.z - modelBBox.min.z)); - + camera.position = (Vector3){ 0.0f, modelBBox.max.y*1.2f, modelSize*3.0f }; - + float decalSize = modelSize*0.25f; float decalOffset = 0.01f; - + Model placementCube = LoadModelFromMesh(GenMeshCube(decalSize, decalSize, decalSize)); placementCube.materials[0].maps[0].color = LIME; - + Material decalMaterial = LoadMaterialDefault(); decalMaterial.maps[0].color = YELLOW; - + Image decalImage = LoadImage("resources/raylib_logo.png"); ImageResizeNN(&decalImage, decalImage.width/4, decalImage.height/4); Texture decalTexture = LoadTextureFromImage(decalImage); UnloadImage(decalImage); - + SetTextureFilter(decalTexture, TEXTURE_FILTER_BILINEAR); decalMaterial.maps[MATERIAL_MAP_DIFFUSE].texture = decalTexture; decalMaterial.maps[MATERIAL_MAP_DIFFUSE].color = RAYWHITE; - + bool showModel = true; Model decalModels[MAX_DECALS] = { 0 }; int decalCount = 0; - + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -151,19 +151,21 @@ int main(void) if (meshHitInfo.hit) collision = meshHitInfo; } - + // Add decal to mesh on hit point if (collision.hit && IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (decalCount < MAX_DECALS)) { // Create the transformation to project the decal Vector3 origin = Vector3Add(collision.point, Vector3Scale(collision.normal, 1.0f)); Matrix splat = MatrixLookAt(collision.point, origin, (Vector3){ 0.0f, 1.0f, 0.0f }); - + // Spin the placement around a bit splat = MatrixMultiply(splat, MatrixRotateZ(DEG2RAD*((float)GetRandomValue(-180, 180)))); - + Mesh decalMesh = GenMeshDecal(model, splat, decalSize, decalOffset); - if (decalMesh.vertexCount > 0) { + + if (decalMesh.vertexCount > 0) + { int decalIndex = decalCount++; decalModels[decalIndex] = LoadModelFromMesh(decalMesh); decalModels[decalIndex].materials[0].maps[0] = decalMaterial.maps[0]; @@ -179,7 +181,7 @@ int main(void) BeginMode3D(camera); // Draw the model at the origin and default scale if (showModel) DrawModel(model, (Vector3){0.0f, 0.0f, 0.0f}, 1.0f, WHITE); - + // Draw the decal models for (int i = 0; i < decalCount; i++) DrawModel(decalModels[i], (Vector3){0}, 1.0f, WHITE); @@ -199,43 +201,45 @@ int main(void) float x0 = GetScreenWidth() - 300; float x1 = x0 + 100; float x2 = x1 + 100; - + DrawText("Vertices", x1, yPos, 10, LIME); DrawText("Triangles", x2, yPos, 10, LIME); yPos += 15; - + int vertexCount = 0; int triangleCount = 0; - + for (int i = 0; i < model.meshCount; i++) { vertexCount += model.meshes[i].vertexCount; triangleCount += model.meshes[i].triangleCount; } - + DrawText("Main model", x0, yPos, 10, LIME); DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); yPos += 15; - + for (int i = 0; i < decalCount; i++) { - if (i == 20) { + if (i == 20) + { DrawText("...", x0, yPos, 10, LIME); yPos += 15; } - - if (i < 20) { + + if (i < 20) + { DrawText(TextFormat("Decal #%d", i+1), x0, yPos, 10, LIME); DrawText(TextFormat("%d", decalModels[i].meshes[0].vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", decalModels[i].meshes[0].triangleCount), x2, yPos, 10, LIME); yPos += 15; } - + vertexCount += decalModels[i].meshes[0].vertexCount; triangleCount += decalModels[i].meshes[0].triangleCount; } - + DrawText("TOTAL", x0, yPos, 10, LIME); DrawText(TextFormat("%d", vertexCount), x1, yPos, 10, LIME); DrawText(TextFormat("%d", triangleCount), x2, yPos, 10, LIME); @@ -243,23 +247,18 @@ int main(void) DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); - + Rectangle rect = (Rectangle){ 10, screenHeight - 100, 100, 60 }; - - if (Button(rect, showModel ? "Hide Model" : "Show Model")) { - showModel = !showModel; - } - + + if (Button(rect, showModel ? "Hide Model" : "Show Model")) showModel = !showModel; + rect.x += rect.width + 10; - - if (Button(rect, "Clear Decals")) { - for (int i = 0; i < decalCount; i++) - { - UnloadModel(decalModels[i]); - } + + if (Button(rect, "Clear Decals")) + { + for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); decalCount = 0; } - DrawFPS(10, 10); @@ -271,15 +270,13 @@ int main(void) //-------------------------------------------------------------------------------------- UnloadModel(model); UnloadTexture(modelTexture); - - for (int i = 0; i < decalCount; i++) { - UnloadModel(decalModels[i]); - } + + // Unload decal models + for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); UnloadTexture(decalTexture); - - // Free the data for decal generation - FreeDecalMeshData(); + + FreeDecalMeshData(); // Free the data for decal generation CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- @@ -298,21 +295,21 @@ static void AddTriangleToMeshBuilder(MeshBuilder *mb, Vector3 vertices[3]) { int newVertexCapacity = (1 + (mb->vertexCapacity/256))*256; Vector3 *newVertices = (Vector3 *)MemAlloc(newVertexCapacity*sizeof(Vector3)); - + if (mb->vertexCapacity > 0) { memcpy(newVertices, mb->vertices, mb->vertexCount*sizeof(Vector3)); MemFree(mb->vertices); } - + mb->vertices = newVertices; mb->vertexCapacity = newVertexCapacity; } - + // Add 3 vertices int index = mb->vertexCount; mb->vertexCount += 3; - + for (int i = 0; i < 3; i++) mb->vertices[index+i] = vertices[i]; } @@ -328,7 +325,7 @@ static void FreeMeshBuilder(MeshBuilder *mb) static Mesh BuildMesh(MeshBuilder *mb) { Mesh outMesh = { 0 }; - + outMesh.vertexCount = mb->vertexCount; outMesh.triangleCount = mb->vertexCount/3; outMesh.vertices = MemAlloc(outMesh.vertexCount*3*sizeof(float)); @@ -339,16 +336,16 @@ static Mesh BuildMesh(MeshBuilder *mb) outMesh.vertices[3*i+0] = mb->vertices[i].x; outMesh.vertices[3*i+1] = mb->vertices[i].y; outMesh.vertices[3*i+2] = mb->vertices[i].z; - + if (mb->uvs) { outMesh.texcoords[2*i+0] = mb->uvs[i].x; outMesh.texcoords[2*i+1] = mb->uvs[i].y; } } - + UploadMesh(&outMesh, false); - + return outMesh; } @@ -364,22 +361,24 @@ static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) return position; } +// Generate mesh decals for provided model static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset) { // We're going to use these to build up our decal meshes // They'll resize automatically as we go, we'll free them at the end static MeshBuilder meshBuilders[2] = { 0 }; - + // Ugly way of telling us to free the static MeshBuilder data - if (inputModel.meshCount == -1) { + if (inputModel.meshCount == -1) + { FreeMeshBuilder(&meshBuilders[0]); FreeMeshBuilder(&meshBuilders[1]); - return (Mesh){0}; + return (Mesh){ 0 }; } - + // We're going to need the inverse matrix Matrix invProj = MatrixInvert(projection); - + // Reset the mesh builders meshBuilders[0].vertexCount = 0; meshBuilders[1].vertexCount = 0; @@ -395,7 +394,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f for (int tri = 0; tri < mesh.triangleCount; tri++) { Vector3 vertices[3] = { 0 }; - + // The way we calculate the vertices of the mesh triangle // depend on whether the mesh vertices are indexed or not if (mesh.indices == 0) @@ -420,7 +419,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f }; } } - + // Transform all 3 vertices of the triangle // and check if they are inside our decal box int insideCount = 0; @@ -428,13 +427,13 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f { // To projection space Vector3 v = Vector3Transform(vertices[i], projection); - + if ((fabsf(v.x) < decalSize) || (fabsf(v.y) <= decalSize) || (fabsf(v.z) <= decalSize)) insideCount++; - + // We need to keep the transformed vertex vertices[i] = v; } - + // If any of them are inside, we add the triangle - we'll clip it later if (insideCount > 0) AddTriangleToMeshBuilder(&meshBuilders[mbIndex], vertices); } @@ -454,15 +453,15 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f { // Swap current model builder (so we read from the one we just wrote to) mbIndex = 1 - mbIndex; - + MeshBuilder *inMesh = &meshBuilders[1 - mbIndex]; MeshBuilder *outMesh = &meshBuilders[mbIndex]; - + // Reset write builder outMesh->vertexCount = 0; - + float s = 0.5f*decalSize; - + for (int i = 0; i < inMesh->vertexCount; i += 3) { Vector3 nV1, nV2, nV3, nV4; @@ -515,7 +514,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f nV3 = ClipSegment(inMesh->vertices[i + 2], nV1, planes[face], s); nV4 = ClipSegment(inMesh->vertices[i + 2], nV2, planes[face], s); } - + AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV4, nV3, nV2}); } break; @@ -529,7 +528,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f nV3 = ClipSegment(nV1, inMesh->vertices[i + 2], planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); } - + if (!v2Out) { nV1 = inMesh->vertices[i + 1]; @@ -537,7 +536,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f nV3 = ClipSegment(nV1, inMesh->vertices[i], planes[face], s); AddTriangleToMeshBuilder(outMesh, (Vector3[3]){nV1, nV2, nV3}); } - + if (!v3Out) { nV1 = inMesh->vertices[i + 2]; @@ -559,21 +558,21 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f if (theMesh->vertexCount > 0) { theMesh->uvs = (Vector2 *)MemAlloc(sizeof(Vector2)*theMesh->vertexCount); - + for (int i = 0; i < theMesh->vertexCount; i++) { // Calculate the UVs based on the projected coords // They are clipped to (-decalSize .. decalSize) and we want them (0..1) theMesh->uvs[i].x = (theMesh->vertices[i].x/decalSize + 0.5f); theMesh->uvs[i].y = (theMesh->vertices[i].y/decalSize + 0.5f); - + // Tiny nudge in the normal direction so it renders properly over the mesh theMesh->vertices[i].z -= decalOffset; - + // From projection space to world space theMesh->vertices[i] = Vector3Transform(theMesh->vertices[i], invProj); } - + // Decal model data ready, create the mesh and return it return BuildMesh(theMesh); } @@ -584,24 +583,25 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f } } -static bool Button(Rectangle rec, char *label) +// Button UI element +static bool Button(Rectangle rec, const char *label) { Color bgColor = GRAY; bool pressed = false; - if (CheckCollisionPointRec(GetMousePosition(), rec)) { + + if (CheckCollisionPointRec(GetMousePosition(), rec)) + { bgColor = LIGHTGRAY; - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - pressed = true; - } + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) pressed = true; } - + DrawRectangleRec(rec, bgColor); DrawRectangleLinesEx(rec, 2.0f, DARKGRAY); - + float fontSize = 10.0f; float textWidth = MeasureText(label, fontSize); - + DrawText(label, (int)(rec.x + rec.width*0.5f - textWidth*0.5f), (int)(rec.y + rec.height*0.5f - fontSize*0.5f), fontSize, DARKGRAY); - + return pressed; -} \ No newline at end of file +} From 0fbc4272d0b6e777a19c212027b4825c90f55f77 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 18:22:23 +0100 Subject: [PATCH 076/102] Remove trailing spaces --- examples/examples_template.c | 2 +- .../shaders/shaders_normalmap_rendering.c | 2 +- examples/shapes/shapes_bullet_hell.c | 2 +- examples/shapes/shapes_starfield_effect.c | 36 +++++++++---------- src/platforms/rcore_desktop_sdl.c | 2 +- src/platforms/rcore_desktop_win32.c | 2 +- src/rcore.c | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/examples_template.c b/examples/examples_template.c index 39a19351d..211749e82 100644 --- a/examples/examples_template.c +++ b/examples/examples_template.c @@ -36,7 +36,7 @@ 10. Have fun! - The following files must be updated when adding a new example, + The following files must be updated when adding a new example, but it can be automatically done using the raylib provided tool: rexm So, no worries if just the .c/.png are provided when adding the example. diff --git a/examples/shaders/shaders_normalmap_rendering.c b/examples/shaders/shaders_normalmap_rendering.c index 4859ec813..07399a78e 100644 --- a/examples/shaders/shaders_normalmap_rendering.c +++ b/examples/shaders/shaders_normalmap_rendering.c @@ -49,7 +49,7 @@ int main(void) camera.projection = CAMERA_PERSPECTIVE; // Load basic normal map lighting shader - Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/normalmap.vs", GLSL_VERSION), + Shader shader = LoadShader(TextFormat("resources/shaders/glsl%i/normalmap.vs", GLSL_VERSION), TextFormat("resources/shaders/glsl%i/normalmap.fs", GLSL_VERSION)); // Get some required shader locations diff --git a/examples/shapes/shapes_bullet_hell.c b/examples/shapes/shapes_bullet_hell.c index 235df4d16..95abc4dc9 100644 --- a/examples/shapes/shapes_bullet_hell.c +++ b/examples/shapes/shapes_bullet_hell.c @@ -197,7 +197,7 @@ int main(void) bullets[i].color); } } - } + } else { // Draw bullets using DrawCircle(), less performant diff --git a/examples/shapes/shapes_starfield_effect.c b/examples/shapes/shapes_starfield_effect.c index 8dd90fe0b..ca409c926 100644 --- a/examples/shapes/shapes_starfield_effect.c +++ b/examples/shapes/shapes_starfield_effect.c @@ -32,18 +32,18 @@ int main(void) const int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - starfield effect"); - + Color bgColor = ColorLerp(DARKBLUE, BLACK, 0.69f); - + // Speed at which we fly forward float speed = 10.0f/9.0f; - + // We're either drawing lines or circles bool drawLines = true; - + Vector3 stars[STAR_COUNT] = { 0 }; Vector2 starsScreenPos[STAR_COUNT] = { 0 }; - + // Setup the stars with a random position for (int i = 0; i < STAR_COUNT; i++) { @@ -65,22 +65,22 @@ int main(void) if ((int)mouseMove != 0) speed += 2.0f*mouseMove/9.0f; if (speed < 0.0f) speed = 0.1f; else if (speed > 2.0f) speed = 2.0f; - + // Toggle lines / points with space bar if (IsKeyPressed(KEY_SPACE)) drawLines = !drawLines; - + float dt = GetFrameTime(); - for (int i = 0; i < STAR_COUNT; i++) + for (int i = 0; i < STAR_COUNT; i++) { // Update star's timer stars[i].z -= dt*speed; - + // Calculate the screen position starsScreenPos[i] = (Vector2){ screenWidth*0.5f + stars[i].x/stars[i].z, screenHeight*0.5f + stars[i].y/stars[i].z, }; - + // If the star is too old, or offscreen, it dies and we make a new random one if ((stars[i].z < 0.0f) || (starsScreenPos[i].x < 0) || (starsScreenPos[i].y < 0.0f) || (starsScreenPos[i].x > screenWidth) || (starsScreenPos[i].y > screenHeight)) @@ -97,14 +97,14 @@ int main(void) BeginDrawing(); ClearBackground(bgColor); - + for (int i = 0; i < STAR_COUNT; i++) { if (drawLines) { // Get the time a little while ago for this star, but clamp it float t = Clamp(stars[i].z + 1.0f/32.0f, 0.0f, 1.0f); - + // If it's different enough from the current time, we proceed if ((t - stars[i].z) > 1e-3) { @@ -113,26 +113,26 @@ int main(void) screenWidth*0.5f + stars[i].x/t, screenHeight*0.5f + stars[i].y/t, }; - + // Draw a line connecting the old point to the current point DrawLineV(startPos, starsScreenPos[i], RAYWHITE); } } - else + else { // Make the radius grow as the star ages float radius = Lerp(stars[i].z, 1.0f, 5.0f); - + // Draw the circle DrawCircleV(starsScreenPos[i], radius, RAYWHITE); } } - + DrawText(TextFormat("[MOUSE WHEEL] Current Speed: %.0f", 9.0f*speed/2.0f), 10, 40, 20, RAYWHITE); DrawText(TextFormat("[SPACE] Current draw mode: %s", drawLines ? "Lines" : "Circles"), 10, 70, 20, RAYWHITE); - + DrawFPS(10, 10); - + EndDrawing(); //---------------------------------------------------------------------------------- } diff --git a/src/platforms/rcore_desktop_sdl.c b/src/platforms/rcore_desktop_sdl.c index e135cd848..03bad80f9 100644 --- a/src/platforms/rcore_desktop_sdl.c +++ b/src/platforms/rcore_desktop_sdl.c @@ -1243,7 +1243,7 @@ void EnableCursor(void) SDL_SetRelativeMouseMode(SDL_FALSE); #if defined(USING_VERSION_SDL3) - // NOTE: SDL_ShowCursor() has been split into three functions: + // NOTE: SDL_ShowCursor() has been split into three functions: // SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible() SDL_ShowCursor(); #else diff --git a/src/platforms/rcore_desktop_win32.c b/src/platforms/rcore_desktop_win32.c index 5b67c72b0..1dadd5586 100644 --- a/src/platforms/rcore_desktop_win32.c +++ b/src/platforms/rcore_desktop_win32.c @@ -1139,7 +1139,7 @@ void ShowCursor(void) // Hides mouse cursor void HideCursor(void) { - // NOTE: We use SetCursor() instead of ShowCursor() because + // NOTE: We use SetCursor() instead of ShowCursor() because // it makes it easy to only hide the cursor while it's inside the client area SetCursor(NULL); CORE.Input.Mouse.cursorHidden = true; diff --git a/src/rcore.c b/src/rcore.c index e4628e77c..d06e3089b 100644 --- a/src/rcore.c +++ b/src/rcore.c @@ -709,7 +709,7 @@ 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 + // NOTE: Current fbo size stored as globals in rlgl for convenience rlglInit(CORE.Window.currentFbo.width, CORE.Window.currentFbo.height); isGpuReady = true; // Flag to note GPU has been initialized successfully From 70f491169836d5cbdcba943d3d49ed83299ca05f Mon Sep 17 00:00:00 2001 From: JordSant <77529699+JordSant@users.noreply.github.com> Date: Sun, 26 Oct 2025 18:24:19 +0100 Subject: [PATCH 077/102] [examples] Added `shaders_color_correction` (#5307) * [examples] Added `shaders_color_correction` * Add _CRT_SECURE_NO_WARNINGS to VS Project * Added to makefiles --- examples/Makefile | 1 + examples/Makefile.Web | 9 + examples/README.md | 5 +- examples/examples_list.txt | 1 + examples/shaders/raygui.h | 5757 +++++++++++++++++ examples/shaders/resources/LICENSE.md | 5 +- examples/shaders/resources/cat.png | Bin 0 -> 388467 bytes examples/shaders/resources/mandrill.png | Bin 0 -> 197452 bytes examples/shaders/resources/parrots.png | Bin 0 -> 294960 bytes .../shaders/glsl100/color_correction.fs | 34 + .../shaders/glsl120/color_correction.fs | 31 + .../shaders/glsl330/color_correction.fs | 34 + examples/shaders/shaders_color_correction.c | 149 + examples/shaders/shaders_color_correction.png | Bin 0 -> 311867 bytes .../examples/shaders_color_correction.vcxproj | 569 ++ projects/VS2022/raylib.sln | 27 + 16 files changed, 6619 insertions(+), 3 deletions(-) create mode 100644 examples/shaders/raygui.h create mode 100644 examples/shaders/resources/cat.png create mode 100644 examples/shaders/resources/mandrill.png create mode 100644 examples/shaders/resources/parrots.png create mode 100644 examples/shaders/resources/shaders/glsl100/color_correction.fs create mode 100644 examples/shaders/resources/shaders/glsl120/color_correction.fs create mode 100644 examples/shaders/resources/shaders/glsl330/color_correction.fs create mode 100644 examples/shaders/shaders_color_correction.c create mode 100644 examples/shaders/shaders_color_correction.png create mode 100644 projects/VS2022/examples/shaders_color_correction.vcxproj diff --git a/examples/Makefile b/examples/Makefile index 9ae8bb480..c601c72b2 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -655,6 +655,7 @@ SHADERS = \ shaders/shaders_ascii_rendering \ shaders/shaders_basic_lighting \ shaders/shaders_basic_pbr \ + shaders/shaders_color_correction \ shaders/shaders_custom_uniform \ shaders/shaders_deferred_rendering \ shaders/shaders_depth_rendering \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 0e9b9f92f..99be781ac 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -655,6 +655,7 @@ SHADERS = \ shaders/shaders_ascii_rendering \ shaders/shaders_basic_lighting \ shaders/shaders_basic_pbr \ + shaders/shaders_color_correction \ shaders/shaders_custom_uniform \ shaders/shaders_deferred_rendering \ shaders/shaders_depth_rendering \ @@ -1261,6 +1262,14 @@ shaders/shaders_basic_pbr: shaders/shaders_basic_pbr.c --preload-file shaders/resources/road_mra.png@resources/road_mra.png \ --preload-file shaders/resources/road_n.png@resources/road_n.png +shapes/shapes_recursive_tree: shaders/shaders_color_correction.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file shaders/resources/shaders/glsl100/color_correction.fs@resources/shaders/glsl100/color_correction.fs \ + --preload-file shaders/resources/parrots.png@resources/parrots.png \ + --preload-file shaders/resources/cat.png@resources/cat.png \ + --preload-file shaders/resources/mandrill.png@resources/mandrill.png \ + --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png + shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/models/barracks.obj@resources/models/barracks.obj \ diff --git a/examples/README.md b/examples/README.md index bbb0a0388..de28c931f 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 187] +## EXAMPLES COLLECTION [TOTAL: 188] ### category: core [45] @@ -196,7 +196,7 @@ Examples using raylib models functionality, including models loading/generation | [models_basic_voxel](models/models_basic_voxel.c) | models_basic_voxel | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) | | [models_rotating_cube](models/models_rotating_cube.c) | models_rotating_cube | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | -### category: shaders [31] +### category: shaders [32] Examples using raylib shaders functionality, including shaders loading, parameters configuration and drawing using them (model shaders and postprocessing shaders). This functionality is directly provided by raylib [rlgl](../src/rlgl.c) module. @@ -233,6 +233,7 @@ Examples using raylib shaders functionality, including shaders loading, paramete | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | shaders_rounded_rectangle | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | | [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | shaders_depth_rendering | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) | | [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | shaders_mandelbrot_set | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | +| [shaders_color_correction](shaders/shaders_color_correction.c) | shaders_color_correction | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | ### category: audio [8] diff --git a/examples/examples_list.txt b/examples/examples_list.txt index 4805a37ec..f24cb9905 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -163,6 +163,7 @@ shaders;shaders_texture_outline;★★★☆;4.0;4.0;2021;2025;"Serenity Skiff"; shaders;shaders_texture_waves;★★☆☆;2.5;3.7;2019;2025;"Anata";@anatagawa shaders;shaders_julia_set;★★★☆;2.5;4.0;2019;2025;"Josh Colclough";@joshcol9232 shaders;shaders_mandelbrot_set;★★★☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant +shaders;shaders_color_correction;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shaders;shaders_eratosthenes_sieve;★★★☆;2.5;4.0;2019;2025;"ProfJski";@ProfJski shaders;shaders_fog_rendering;★★★☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_simple_mask;★★☆☆;2.5;3.7;2019;2025;"Chris Camacho";@chriscamacho diff --git a/examples/shaders/raygui.h b/examples/shaders/raygui.h new file mode 100644 index 000000000..a3fc51f0f --- /dev/null +++ b/examples/shaders/raygui.h @@ -0,0 +1,5757 @@ +/******************************************************************************************* +* +* 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 +* available as a standalone library, as long as input and drawing functions are provided. +* +* FEATURES: +* - Immediate-mode gui, minimal retained data +* - +25 controls provided (basic and advanced) +* - Styling system for colors, font and metrics +* - Icons supported, embedded as a 1-bit icons pack +* - Standalone mode option (custom input/graphics backend) +* - Multiple support tools provided for raygui development +* +* POSSIBLE IMPROVEMENTS: +* - Better standalone mode API for easy plug of custom backends +* - Externalize required inputs, allow user easier customization +* +* LIMITATIONS: +* - No editable multi-line word-wraped text box supported +* - No auto-layout mechanism, up to the user to define controls position and size +* - Standalone mode requires library modification and some user work to plug another backend +* +* 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 GuiLoadStyleDefault() unloads +* by default any previously loaded font (texture, recs, glyphs). +* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions +* +* CONTROLS PROVIDED: +* # Container/separators Controls +* - WindowBox --> StatusBar, Panel +* - GroupBox --> Line +* - Line +* - Panel --> StatusBar +* - ScrollPanel --> StatusBar +* - TabBar --> Button +* +* # Basic Controls +* - Label +* - LabelButton --> Label +* - Button +* - Toggle +* - ToggleGroup --> Toggle +* - ToggleSlider +* - CheckBox +* - ComboBox +* - DropdownBox +* - TextBox +* - ValueBox --> TextBox +* - Spinner --> Button, ValueBox +* - Slider +* - SliderBar --> Slider +* - ProgressBar +* - StatusBar +* - DummyRec +* - Grid +* +* # Advance Controls +* - ListView +* - ColorPicker --> ColorPanel, ColorBarHue +* - MessageBox --> Window, Label, Button +* - TextInputBox --> Window, Label, TextBox, Button +* +* It also provides a set of functions for styling the controls based on its properties (size, color). +* +* +* RAYGUI STYLE (guiStyle): +* raygui uses a global data array for all gui style properties (allocated on data segment by default), +* when a new style is loaded, it is loaded over the global style... but a default gui style could always be +* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one +* +* The global style array size is fixed and depends on the number of controls and properties: +* +* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)]; +* +* guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +* +* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style +* used for all controls, when any of those base values is set, it is automatically populated to all +* controls, so, specific control values overwriting generic style should be set after base values. +* +* After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those +* properties are actually common to all controls and can not be overwritten individually (like BASE ones) +* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR +* +* Custom control properties can be defined using the EXTENDED properties for each independent control. +* +* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler +* +* +* RAYGUI ICONS (guiIcons): +* raygui could use a global array containing icons data (allocated on data segment by default), +* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set +* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded +* +* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon +* requires 8 integers (16*16/32) to be stored in memory. +* +* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set. +* +* The global icons array size is fixed and depends on the number of icons and size: +* +* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS]; +* +* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +* +* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons +* +* RAYGUI LAYOUT: +* raygui currently does not provide an auto-layout mechanism like other libraries, +* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it. +* +* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout +* +* CONFIGURATION: +* #define RAYGUI_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* #define RAYGUI_STANDALONE +* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined +* internally in the library and input management and drawing functions must be provided by +* the user (check library implementation for further details). +* +* #define RAYGUI_NO_ICONS +* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB) +* +* #define RAYGUI_CUSTOM_ICONS +* Includes custom ricons.h header defining a set of custom icons, +* this file can be generated using rGuiIcons tool +* +* #define RAYGUI_DEBUG_RECS_BOUNDS +* Draw control bounds rectangles for debug +* +* #define RAYGUI_DEBUG_TEXT_BOUNDS +* 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 +* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE +* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode +* ADDED: Support loading styles with custom font charset from external file +* REDESIGNED: GuiTextBox(), support mouse cursor positioning +* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only) +* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color +* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText() +* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value +* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value +* REDESIGNED: GuiComboBox(), get parameters by reference and return result value +* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value +* REDESIGNED: GuiSlider(), get parameters by reference and return result value +* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value +* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value +* REDESIGNED: GuiListView(), get parameters by reference and return result value +* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value +* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), added extra parameter +* REDESIGNED: GuiListViewEx(), change parameters order +* REDESIGNED: All controls return result as int value +* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars +* REVIEWED: All examples and specially controls_test_suite +* RENAMED: gui_file_dialog module to gui_window_file_dialog +* UPDATED: All styles to include ISO-8859-15 charset (as much as possible) +* +* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER +* ADDED: GuiLoadStyleFromMemory() (binary only) +* REVIEWED: GuiScrollBar() horizontal movement key +* REVIEWED: GuiTextBox() crash on cursor movement +* REVIEWED: GuiTextBox(), additional inputs support +* REVIEWED: GuiLabelButton(), avoid text cut +* REVIEWED: GuiTextInputBox(), password input +* REVIEWED: Local GetCodepointNext(), aligned with raylib +* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds +* +* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle() +* ADDED: Helper functions to split text in separate lines +* ADDED: Multiple new icons, useful for code editing tools +* REMOVED: Unneeded icon editing functions +* REMOVED: GuiTextBoxMulti(), very limited and broken +* REMOVED: MeasureTextEx() dependency, logic directly implemented +* REMOVED: DrawTextEx() dependency, logic directly implemented +* REVIEWED: GuiScrollBar(), improve mouse-click behaviour +* REVIEWED: Library header info, more info, better organized +* REDESIGNED: GuiTextBox() to support cursor movement +* REDESIGNED: GuiDrawText() to divide drawing by lines +* +* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes +* REMOVED: GuiScrollBar(), only internal +* REDESIGNED: GuiPanel() to support text parameter +* REDESIGNED: GuiScrollPanel() to support text parameter +* REDESIGNED: GuiColorPicker() to support text parameter +* REDESIGNED: GuiColorPanel() to support text parameter +* REDESIGNED: GuiColorBarAlpha() to support text parameter +* REDESIGNED: GuiColorBarHue() to support text parameter +* REDESIGNED: GuiTextInputBox() to support password +* +* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool) +* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures +* REVIEWED: External icons usage logic +* REVIEWED: GuiLine() for centered alignment when including text +* RENAMED: Multiple controls properties definitions to prepend RAYGUI_ +* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency +* Projects updated and multiple tweaks +* +* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file +* REDESIGNED: GuiTextBoxMulti() +* REMOVED: GuiImageButton*() +* Multiple minor tweaks and bugs corrected +* +* 2.9 (17-Mar-2021) REMOVED: Tooltip API +* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle() +* 2.7 (20-Feb-2020) ADDED: Possible tooltips API +* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox() +* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox() +* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle() +* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties +* ADDED: 8 new custom styles ready to use +* Multiple minor tweaks and bugs corrected +* +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* REDESIGNED: Style system (breaking change) +* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts +* REVIEWED: GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout +* 1.5 (21-Jun-2017) Working in an improved styles system +* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) +* 1.3 (12-Jun-2017) Complete redesign of style system +* 1.1 (01-Jun-2017) Complete review of the library +* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria. +* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria. +* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria. +* +* DEPENDENCIES: +* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* +* STANDALONE MODE: +* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled +* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs. +* +* The following functions should be redefined for a custom backend: +* +* - Vector2 GetMousePosition(void); +* - float GetMouseWheelMove(void); +* - bool IsMouseButtonDown(int button); +* - bool IsMouseButtonPressed(int button); +* - bool IsMouseButtonReleased(int button); +* - bool IsKeyDown(int key); +* - bool IsKeyPressed(int key); +* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +* +* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +* +* - Font GetFontDefault(void); // -- GuiLoadStyleDefault() +* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle() +* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) +* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data +* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs +* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list +* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, redesign, update and maintenance +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) +* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) +* Adria Arranz: Testing and implementation of additional controls (2018) +* Jordi Jorba: Testing and implementation of additional controls (2018) +* Albert Martos: Review and testing of the library (2015) +* Ian Eito: Review and testing of the library (2015) +* Kevin Gato: Initial implementation of basic components (2014) +* Daniel Nicolas: Initial implementation of basic components (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2024 Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYGUI_H +#define RAYGUI_H + +#define RAYGUI_VERSION_MAJOR 4 +#define RAYGUI_VERSION_MINOR 5 +#define RAYGUI_VERSION_PATCH 0 +#define RAYGUI_VERSION "4.5-dev" + +#if !defined(RAYGUI_STANDALONE) + #include "raylib.h" +#endif + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) + #endif +#endif + +// Function specifiers definition +#ifndef RAYGUIAPI + #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Allow custom memory allocators +#ifndef RAYGUI_MALLOC + #define RAYGUI_MALLOC(sz) malloc(sz) +#endif +#ifndef RAYGUI_CALLOC + #define RAYGUI_CALLOC(n,sz) calloc(n,sz) +#endif +#ifndef RAYGUI_FREE + #define RAYGUI_FREE(p) free(p) +#endif + +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define RAYGUI_SUPPORT_LOG_INFO +#if defined(RAYGUI_SUPPORT_LOG_INFO) + #define RAYGUI_LOG(...) printf(__VA_ARGS__) +#else + #define RAYGUI_LOG(...) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Some types are required for RAYGUI_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + #ifndef __cplusplus + // Boolean type + #ifndef true + typedef enum { false, true } bool; + #endif + #endif + + // Vector2 type + typedef struct Vector2 { + float x; + float y; + } Vector2; + + // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV() + typedef struct Vector3 { + float x; + float y; + float z; + } Vector3; + + // Color type, RGBA (32bit) + typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } Color; + + // Rectangle type + typedef struct Rectangle { + float x; + float y; + float width; + float height; + } Rectangle; + + // TODO: Texture2D type is very coupled to raylib, required by Font type + // It should be redesigned to be provided by user + typedef struct Texture2D { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Texture2D; + + // Image, pixel data stored in CPU memory (RAM) + typedef struct Image { + void *data; // Image raw data + int width; // Image base width + int height; // Image base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Image; + + // GlyphInfo, font characters glyphs info + typedef struct GlyphInfo { + int value; // Character value (Unicode) + int offsetX; // Character offset X when drawing + int offsetY; // Character offset Y when drawing + int advanceX; // Character advance position X + Image image; // Character image data + } GlyphInfo; + + // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle() + // It should be redesigned to be provided by user + typedef struct Font { + int baseSize; // Base size (default chars height) + int glyphCount; // Number of glyph characters + int glyphPadding; // Padding around the glyph characters + Texture2D texture; // Texture atlas containing the glyphs + Rectangle *recs; // Rectangles in texture for the glyphs + GlyphInfo *glyphs; // Glyphs info data + } Font; +#endif + +// Style property +// NOTE: Used when exporting style as code for convenience +typedef struct GuiStyleProp { + unsigned short controlId; // Control identifier + unsigned short propertyId; // Property identifier + int propertyValue; // Property value +} GuiStyleProp; + +/* +// Controls text style -NOT USED- +// NOTE: Text style is defined by control +typedef struct GuiTextStyle { + unsigned int size; + int charSpacing; + int lineSpacing; + int alignmentH; + int alignmentV; + int padding; +} GuiTextStyle; +*/ + +// Gui control state +typedef enum { + STATE_NORMAL = 0, + STATE_FOCUSED, + STATE_PRESSED, + STATE_DISABLED +} GuiState; + +// Gui control text alignment +typedef enum { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT +} GuiTextAlignment; + +// Gui control text alignment vertical +// NOTE: Text vertical position inside the text bounds +typedef enum { + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_MIDDLE, + TEXT_ALIGN_BOTTOM +} GuiTextAlignmentVertical; + +// Gui control text wrap mode +// NOTE: Useful for multiline text +typedef enum { + TEXT_WRAP_NONE = 0, + TEXT_WRAP_CHAR, + TEXT_WRAP_WORD +} GuiTextWrapMode; + +// Gui controls +typedef enum { + // Default -> populates to all controls when set + DEFAULT = 0, + + // Basic controls + LABEL, // Used also for: LABELBUTTON + BUTTON, + TOGGLE, // Used also for: TOGGLEGROUP + SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER + PROGRESSBAR, + CHECKBOX, + COMBOBOX, + DROPDOWNBOX, + TEXTBOX, // Used also for: TEXTBOXMULTI + VALUEBOX, + SPINNER, // Uses: BUTTON, VALUEBOX + LISTVIEW, + COLORPICKER, + SCROLLBAR, + STATUSBAR +} GuiControl; + +// Gui base properties for every control +// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties) +typedef enum { + BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL + BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL + TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL + BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED + BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED + TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED + BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED + BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED + TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED + BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED + BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED + TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED + BORDER_WIDTH, // Control border size, 0 for no border + //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls + //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls + //TEXT_LINE_SPACING // Control text spacing between lines -> GLOBAL for all controls + TEXT_PADDING, // Control text padding, not considering border + TEXT_ALIGNMENT, // Control text horizontal alignment inside control text bound (after border and padding) + //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls +} GuiControlProperty; + +// TODO: Which text styling properties should be global or per-control? +// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while +// 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) +//---------------------------------------------------------------------------------- +// DEFAULT extended properties +// NOTE: Those properties are common to all controls or global +// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT? +typedef enum { + TEXT_SIZE = 16, // Text size (glyphs max height) + TEXT_SPACING, // Text spacing between glyphs + LINE_COLOR, // Line control color + BACKGROUND_COLOR, // Background color + TEXT_LINE_SPACING, // Text spacing between lines + 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 thickness +} GuiDefaultProperty; + +// Other possible text properties: +// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... + +// Label +//typedef enum { } GuiLabelProperty; + +// Button/Spinner +//typedef enum { } GuiButtonProperty; + +// Toggle/ToggleGroup +typedef enum { + GROUP_PADDING = 16, // ToggleGroup separation between toggles +} GuiToggleProperty; + +// Slider/SliderBar +typedef enum { + SLIDER_WIDTH = 16, // Slider size of internal bar + SLIDER_PADDING // Slider/SliderBar internal bar padding +} GuiSliderProperty; + +// ProgressBar +typedef enum { + PROGRESS_PADDING = 16, // ProgressBar internal padding +} GuiProgressBarProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, // ScrollBar arrows size + ARROWS_VISIBLE, // ScrollBar arrows visible + SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding + SCROLL_SLIDER_SIZE, // ScrollBar slider size + SCROLL_PADDING, // ScrollBar scroll padding from arrows + SCROLL_SPEED, // ScrollBar scrolling speed +} GuiScrollBarProperty; + +// CheckBox +typedef enum { + CHECK_PADDING = 16 // CheckBox internal check padding +} GuiCheckBoxProperty; + +// ComboBox +typedef enum { + COMBO_BUTTON_WIDTH = 16, // ComboBox right button width + COMBO_BUTTON_SPACING // ComboBox button separation +} GuiComboBoxProperty; + +// DropdownBox +typedef enum { + ARROW_PADDING = 16, // DropdownBox arrow separation from border and items + 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 +typedef enum { + TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable +} GuiTextBoxProperty; + +// Spinner +typedef enum { + SPIN_BUTTON_WIDTH = 16, // Spinner left/right buttons width + SPIN_BUTTON_SPACING, // Spinner buttons separation +} GuiSpinnerProperty; + +// ListView +typedef enum { + LIST_ITEMS_HEIGHT = 16, // ListView items height + 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 +typedef enum { + COLOR_SELECTOR_SIZE = 16, + HUEBAR_WIDTH, // ColorPicker right hue bar width + HUEBAR_PADDING, // ColorPicker right hue bar separation from panel + HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height + HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow +} GuiColorPickerProperty; + +#define SCROLLBAR_LEFT_SIDE 0 +#define SCROLLBAR_RIGHT_SIDE 1 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Global gui state control functions +RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state) +RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state) +RAYGUIAPI void GuiLock(void); // Lock gui controls (global state) +RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state) +RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state) +RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f +RAYGUIAPI void GuiSetState(int state); // Set gui state (global state) +RAYGUIAPI int GuiGetState(void); // Get gui state (global state) + +// Font set/get functions +RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state) +RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state) + +// Style set/get functions +RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property +RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property + +// Styles loading functions +RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs) +RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style + +// Tooltips management functions +RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state) +RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state) +RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string + +// Icons functionality +RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported) +#if !defined(RAYGUI_NO_ICONS) +RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size +RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer +RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data +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 +RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed +RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name +RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text +RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls +RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 +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 +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, 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 + +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 +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 + +// Advance controls set +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 +RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) +RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control +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 updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() +//---------------------------------------------------------------------------------------------------------- + +#if !defined(RAYGUI_NO_ICONS) + +#if !defined(RAYGUI_CUSTOM_ICONS) +//---------------------------------------------------------------------------------- +// Icons enumeration +//---------------------------------------------------------------------------------- +typedef enum { + ICON_NONE = 0, + ICON_FOLDER_FILE_OPEN = 1, + ICON_FILE_SAVE_CLASSIC = 2, + ICON_FOLDER_OPEN = 3, + ICON_FOLDER_SAVE = 4, + ICON_FILE_OPEN = 5, + ICON_FILE_SAVE = 6, + ICON_FILE_EXPORT = 7, + ICON_FILE_ADD = 8, + ICON_FILE_DELETE = 9, + ICON_FILETYPE_TEXT = 10, + ICON_FILETYPE_AUDIO = 11, + ICON_FILETYPE_IMAGE = 12, + ICON_FILETYPE_PLAY = 13, + ICON_FILETYPE_VIDEO = 14, + ICON_FILETYPE_INFO = 15, + ICON_FILE_COPY = 16, + ICON_FILE_CUT = 17, + ICON_FILE_PASTE = 18, + ICON_CURSOR_HAND = 19, + ICON_CURSOR_POINTER = 20, + ICON_CURSOR_CLASSIC = 21, + ICON_PENCIL = 22, + ICON_PENCIL_BIG = 23, + ICON_BRUSH_CLASSIC = 24, + ICON_BRUSH_PAINTER = 25, + ICON_WATER_DROP = 26, + ICON_COLOR_PICKER = 27, + ICON_RUBBER = 28, + ICON_COLOR_BUCKET = 29, + ICON_TEXT_T = 30, + ICON_TEXT_A = 31, + ICON_SCALE = 32, + ICON_RESIZE = 33, + ICON_FILTER_POINT = 34, + ICON_FILTER_BILINEAR = 35, + ICON_CROP = 36, + ICON_CROP_ALPHA = 37, + ICON_SQUARE_TOGGLE = 38, + ICON_SYMMETRY = 39, + ICON_SYMMETRY_HORIZONTAL = 40, + ICON_SYMMETRY_VERTICAL = 41, + ICON_LENS = 42, + ICON_LENS_BIG = 43, + ICON_EYE_ON = 44, + ICON_EYE_OFF = 45, + ICON_FILTER_TOP = 46, + ICON_FILTER = 47, + ICON_TARGET_POINT = 48, + ICON_TARGET_SMALL = 49, + ICON_TARGET_BIG = 50, + ICON_TARGET_MOVE = 51, + ICON_CURSOR_MOVE = 52, + ICON_CURSOR_SCALE = 53, + ICON_CURSOR_SCALE_RIGHT = 54, + ICON_CURSOR_SCALE_LEFT = 55, + ICON_UNDO = 56, + ICON_REDO = 57, + ICON_REREDO = 58, + ICON_MUTATE = 59, + ICON_ROTATE = 60, + ICON_REPEAT = 61, + ICON_SHUFFLE = 62, + ICON_EMPTYBOX = 63, + ICON_TARGET = 64, + ICON_TARGET_SMALL_FILL = 65, + ICON_TARGET_BIG_FILL = 66, + ICON_TARGET_MOVE_FILL = 67, + ICON_CURSOR_MOVE_FILL = 68, + ICON_CURSOR_SCALE_FILL = 69, + ICON_CURSOR_SCALE_RIGHT_FILL = 70, + ICON_CURSOR_SCALE_LEFT_FILL = 71, + ICON_UNDO_FILL = 72, + ICON_REDO_FILL = 73, + ICON_REREDO_FILL = 74, + ICON_MUTATE_FILL = 75, + ICON_ROTATE_FILL = 76, + ICON_REPEAT_FILL = 77, + ICON_SHUFFLE_FILL = 78, + ICON_EMPTYBOX_SMALL = 79, + ICON_BOX = 80, + ICON_BOX_TOP = 81, + ICON_BOX_TOP_RIGHT = 82, + ICON_BOX_RIGHT = 83, + ICON_BOX_BOTTOM_RIGHT = 84, + ICON_BOX_BOTTOM = 85, + ICON_BOX_BOTTOM_LEFT = 86, + ICON_BOX_LEFT = 87, + ICON_BOX_TOP_LEFT = 88, + ICON_BOX_CENTER = 89, + ICON_BOX_CIRCLE_MASK = 90, + ICON_POT = 91, + ICON_ALPHA_MULTIPLY = 92, + ICON_ALPHA_CLEAR = 93, + ICON_DITHERING = 94, + ICON_MIPMAPS = 95, + ICON_BOX_GRID = 96, + ICON_GRID = 97, + ICON_BOX_CORNERS_SMALL = 98, + ICON_BOX_CORNERS_BIG = 99, + ICON_FOUR_BOXES = 100, + ICON_GRID_FILL = 101, + ICON_BOX_MULTISIZE = 102, + ICON_ZOOM_SMALL = 103, + ICON_ZOOM_MEDIUM = 104, + ICON_ZOOM_BIG = 105, + ICON_ZOOM_ALL = 106, + ICON_ZOOM_CENTER = 107, + ICON_BOX_DOTS_SMALL = 108, + ICON_BOX_DOTS_BIG = 109, + ICON_BOX_CONCENTRIC = 110, + ICON_BOX_GRID_BIG = 111, + ICON_OK_TICK = 112, + ICON_CROSS = 113, + ICON_ARROW_LEFT = 114, + ICON_ARROW_RIGHT = 115, + ICON_ARROW_DOWN = 116, + ICON_ARROW_UP = 117, + ICON_ARROW_LEFT_FILL = 118, + ICON_ARROW_RIGHT_FILL = 119, + ICON_ARROW_DOWN_FILL = 120, + ICON_ARROW_UP_FILL = 121, + ICON_AUDIO = 122, + ICON_FX = 123, + ICON_WAVE = 124, + ICON_WAVE_SINUS = 125, + ICON_WAVE_SQUARE = 126, + ICON_WAVE_TRIANGULAR = 127, + ICON_CROSS_SMALL = 128, + ICON_PLAYER_PREVIOUS = 129, + ICON_PLAYER_PLAY_BACK = 130, + ICON_PLAYER_PLAY = 131, + ICON_PLAYER_PAUSE = 132, + ICON_PLAYER_STOP = 133, + ICON_PLAYER_NEXT = 134, + ICON_PLAYER_RECORD = 135, + ICON_MAGNET = 136, + ICON_LOCK_CLOSE = 137, + ICON_LOCK_OPEN = 138, + ICON_CLOCK = 139, + ICON_TOOLS = 140, + ICON_GEAR = 141, + ICON_GEAR_BIG = 142, + ICON_BIN = 143, + ICON_HAND_POINTER = 144, + ICON_LASER = 145, + ICON_COIN = 146, + ICON_EXPLOSION = 147, + ICON_1UP = 148, + ICON_PLAYER = 149, + ICON_PLAYER_JUMP = 150, + ICON_KEY = 151, + ICON_DEMON = 152, + ICON_TEXT_POPUP = 153, + ICON_GEAR_EX = 154, + ICON_CRACK = 155, + ICON_CRACK_POINTS = 156, + ICON_STAR = 157, + ICON_DOOR = 158, + ICON_EXIT = 159, + ICON_MODE_2D = 160, + ICON_MODE_3D = 161, + ICON_CUBE = 162, + ICON_CUBE_FACE_TOP = 163, + ICON_CUBE_FACE_LEFT = 164, + ICON_CUBE_FACE_FRONT = 165, + ICON_CUBE_FACE_BOTTOM = 166, + ICON_CUBE_FACE_RIGHT = 167, + ICON_CUBE_FACE_BACK = 168, + ICON_CAMERA = 169, + ICON_SPECIAL = 170, + ICON_LINK_NET = 171, + ICON_LINK_BOXES = 172, + ICON_LINK_MULTI = 173, + ICON_LINK = 174, + ICON_LINK_BROKE = 175, + ICON_TEXT_NOTES = 176, + ICON_NOTEBOOK = 177, + ICON_SUITCASE = 178, + ICON_SUITCASE_ZIP = 179, + ICON_MAILBOX = 180, + ICON_MONITOR = 181, + ICON_PRINTER = 182, + ICON_PHOTO_CAMERA = 183, + ICON_PHOTO_CAMERA_FLASH = 184, + ICON_HOUSE = 185, + ICON_HEART = 186, + ICON_CORNER = 187, + ICON_VERTICAL_BARS = 188, + ICON_VERTICAL_BARS_FILL = 189, + ICON_LIFE_BARS = 190, + ICON_INFO = 191, + ICON_CROSSLINE = 192, + ICON_HELP = 193, + ICON_FILETYPE_ALPHA = 194, + ICON_FILETYPE_HOME = 195, + ICON_LAYERS_VISIBLE = 196, + ICON_LAYERS = 197, + ICON_WINDOW = 198, + ICON_HIDPI = 199, + ICON_FILETYPE_BINARY = 200, + ICON_HEX = 201, + ICON_SHIELD = 202, + ICON_FILE_NEW = 203, + ICON_FOLDER_ADD = 204, + ICON_ALARM = 205, + ICON_CPU = 206, + ICON_ROM = 207, + ICON_STEP_OVER = 208, + ICON_STEP_INTO = 209, + ICON_STEP_OUT = 210, + ICON_RESTART = 211, + ICON_BREAKPOINT_ON = 212, + ICON_BREAKPOINT_OFF = 213, + ICON_BURGER_MENU = 214, + ICON_CASE_SENSITIVE = 215, + ICON_REG_EXP = 216, + ICON_FOLDER = 217, + ICON_FILE = 218, + ICON_SAND_TIMER = 219, + 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_HOT = 228, + ICON_229 = 229, + ICON_230 = 230, + ICON_231 = 231, + ICON_232 = 232, + ICON_233 = 233, + ICON_234 = 234, + ICON_235 = 235, + ICON_236 = 236, + ICON_237 = 237, + ICON_238 = 238, + ICON_239 = 239, + ICON_240 = 240, + ICON_241 = 241, + ICON_242 = 242, + ICON_243 = 243, + ICON_244 = 244, + ICON_245 = 245, + ICON_246 = 246, + ICON_247 = 247, + ICON_248 = 248, + ICON_249 = 249, + ICON_250 = 250, + ICON_251 = 251, + ICON_252 = 252, + ICON_253 = 253, + ICON_254 = 254, + ICON_255 = 255, +} GuiIconName; +#endif + +#endif + +#if defined(__cplusplus) +} // Prevents name mangling of functions +#endif + +#endif // RAYGUI_H + +/*********************************************************************************** +* +* RAYGUI IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RAYGUI_IMPLEMENTATION) + +#include // required for: isspace() [GuiTextBox()] +#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() +#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()] +#include // Required for: roundf() [GuiColorPicker()] + +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + +// Check if two rectangles are equal, used to validate a slider bounds as an id +#ifndef CHECK_BOUNDS_ID + #define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height)) +#endif + +#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS) + +// Embedded icons, no external file provided +#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared) +#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons +#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id + +// Icons data is defined by bit array (every bit represents one pixel) +// Those arrays are stored as unsigned int data arrays, so, +// every array element defines 32 pixels (bits) of information +// One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels) +// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels) +#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32) + +//---------------------------------------------------------------------------------- +// Icons data for all gui possible icons (allocated on data segment by default) +// +// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so, +// every 16x16 icon requires 8 integers (16*16/32) to be stored +// +// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(), +// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS +// +// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +//---------------------------------------------------------------------------------- +static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE + 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN + 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE + 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT + 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO + 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE + 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY + 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO + 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO + 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY + 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT + 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE + 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND + 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER + 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC + 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL + 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG + 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC + 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER + 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP + 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER + 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER + 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET + 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T + 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A + 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE + 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE + 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT + 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR + 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP + 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA + 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE + 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY + 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL + 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL + 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS + 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG + 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON + 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF + 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP + 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER + 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT + 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL + 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG + 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE + 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE + 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE + 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT + 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT + 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO + 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE + 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT + 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE + 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX + 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET + 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL + 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL + 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL + 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL + 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL + 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL + 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL + 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL + 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL + 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX + 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP + 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT + 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER + 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK + 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR + 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING + 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS + 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID + 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID + 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL + 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG + 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES + 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL + 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE + 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL + 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM + 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG + 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL + 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER + 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL + 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG + 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC + 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG + 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK + 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS + 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT + 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT + 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN + 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP + 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL + 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL + 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL + 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL + 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO + 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX + 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE + 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS + 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE + 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR + 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL + 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS + 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK + 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY + 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE + 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP + 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT + 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD + 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET + 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE + 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN + 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK + 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS + 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR + 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG + 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN + 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER + 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER + 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN + 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION + 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP + 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER + 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP + 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY + 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON + 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP + 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX + 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK + 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS + 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR + 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR + 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT + 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D + 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE + 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP + 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM + 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT + 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK + 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA + 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL + 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET + 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES + 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI + 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK + 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE + 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES + 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK + 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE + 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP + 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX + 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR + 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER + 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA + 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH + 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE + 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER + 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS + 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL + 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS + 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO + 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE + 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP + 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA + 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME + 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE + 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS + 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW + 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI + 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY + 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX + 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD + 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW + 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD + 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM + 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU + 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM + 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER + 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO + 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT + 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART + 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON + 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF + 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU + 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE + 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP + 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 + 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 + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_229 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_230 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_231 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_232 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_233 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 +}; + +// NOTE: A pointer to current icons array should be defined +static unsigned int *guiIconsPtr = guiIcons; + +#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS + +#ifndef RAYGUI_ICON_SIZE + #define RAYGUI_ICON_SIZE 0 +#endif + +// WARNING: Those values define the total size of the style data array, +// if changed, previous saved styles could become incompatible +#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls +#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties +#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// Gui control property style color element +typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state + +static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib) +static bool guiLocked = false; // Gui lock state (no inputs processed) +static float guiAlpha = 1.0f; // Gui controls transparency + +static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled) + +static bool guiTooltip = false; // Tooltip enabled/disabled +static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) + +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 +static int autoCursorCooldownCounter = 0; // Cooldown frame counter for automatic cursor movement on key-down +static int autoCursorDelayCounter = 0; // Delay frame counter for automatic cursor movement + +//---------------------------------------------------------------------------------- +// Style data array for all gui style properties (allocated on data segment by default) +// +// NOTE 1: First set of BASE properties are generic to all controls but could be individually +// overwritten per control, first set of EXTENDED properties are generic to all controls and +// can not be overwritten individually but custom EXTENDED properties can be used by control +// +// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(), +// but default gui style could always be recovered with GuiLoadStyleDefault() +// +// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +//---------------------------------------------------------------------------------- +static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 }; + +static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization + +//---------------------------------------------------------------------------------- +// Standalone Mode Functions Declaration +// +// NOTE: raygui depend on some raylib input and drawing functions +// To use raygui as standalone library, below functions must be defined by the user +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + +#define KEY_RIGHT 262 +#define KEY_LEFT 263 +#define KEY_DOWN 264 +#define KEY_UP 265 +#define KEY_BACKSPACE 259 +#define KEY_ENTER 257 + +#define MOUSE_LEFT_BUTTON 0 + +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static float GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); + +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +//------------------------------------------------------------------------------- + +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font + +static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) + +static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data + +static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs + +static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list + +static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui +//------------------------------------------------------------------------------- +static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value +static int ColorToInt(Color color); // Returns hexadecimal value for a Color +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +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) + +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient +//------------------------------------------------------------------------------- + +#endif // RAYGUI_STANDALONE + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only) + +static int GetTextWidth(const char *text); // Gui get text width using gui font and style +static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds +static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor + +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style + +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings +static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB +static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV + +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel() +static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position + +static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor + +//---------------------------------------------------------------------------------- +// Gui Setup Functions Definition +//---------------------------------------------------------------------------------- +// Enable gui global state +// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups +void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; } + +// Disable gui global state +// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups +void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; } + +// Lock gui global state +void GuiLock(void) { guiLocked = true; } + +// Unlock gui global state +void GuiUnlock(void) { guiLocked = false; } + +// Check if gui is locked (global state) +bool GuiIsLocked(void) { return guiLocked; } + +// Set gui controls alpha global state +void GuiSetAlpha(float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + guiAlpha = alpha; +} + +// Set gui state (global state) +void GuiSetState(int state) { guiState = (GuiState)state; } + +// Get gui state (global state) +int GuiGetState(void) { return guiState; } + +// Set custom gui font +// NOTE: Font loading/unloading is external to raygui +void GuiSetFont(Font font) +{ + if (font.texture.id > 0) + { + // NOTE: If we try to setup a font but default style has not been + // lazily loaded before, it will be overwritten, so we need to force + // default style loading first + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + guiFont = font; + } +} + +// Get custom gui font +Font GuiGetFont(void) +{ + return guiFont; +} + +// Set control style property value +void GuiSetStyle(int control, int property, int value) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + + // Default properties are propagated to all controls + if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE)) + { + for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + } +} + +// Get control style property value +int GuiGetStyle(int control, int property) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property]; +} + +//---------------------------------------------------------------------------------- +// Gui Controls Functions Definition +//---------------------------------------------------------------------------------- + +// Window Box control +int GuiWindowBox(Rectangle bounds, const char *title) +{ + // Window title bar height (including borders) + // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox() + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + int result = 0; + //GuiState state = guiState; + + int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight }; + if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f; + + Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 }; + Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - 20, + statusBar.y + statusBarHeight/2.0f - 18.0f/2.0f, 18, 18 }; + + // Update control + //-------------------------------------------------------------------- + // NOTE: Logic is directly managed by button + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiStatusBar(statusBar, title); // Draw window header as status bar + GuiPanel(windowPanel, NULL); // Draw window base + + // Draw window close button + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + result = GuiButton(closeButtonRec, "x"); +#else + result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL)); +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + //-------------------------------------------------------------------- + + return result; // Window close button clicked: result = 1 +} + +// Group Box control with text name +int GuiGroupBox(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_GROUPBOX_LINE_THICK) + #define RAYGUI_GROUPBOX_LINE_THICK 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); + //-------------------------------------------------------------------- + + return result; +} + +// Line control +int GuiLine(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_LINE_ORIGIN_SIZE) + #define RAYGUI_LINE_MARGIN_TEXT 12 + #endif + #if !defined(RAYGUI_LINE_TEXT_PADDING) + #define RAYGUI_LINE_TEXT_PADDING 4 + #endif + + int result = 0; + GuiState state = guiState; + + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); + + // Draw control + //-------------------------------------------------------------------- + if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color); + else + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text) + 2; + textBounds.height = bounds.height; + textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT; + textBounds.y = bounds.y; + + // Draw line with embedded text label: "--- text --------------" + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + } + //-------------------------------------------------------------------- + + return result; +} + +// Panel control +int GuiPanel(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_PANEL_BORDER_WIDTH) + #define RAYGUI_PANEL_BORDER_WIDTH 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + } + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED: (int)LINE_COLOR)), + GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? BASE_COLOR_DISABLED : BACKGROUND_COLOR))); + //-------------------------------------------------------------------- + + return result; +} + +// Tab Bar control +// NOTE: Using GuiToggle() for the TABS +int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) +{ + #define RAYGUI_TABBAR_ITEM_WIDTH 160 + + int result = -1; + //GuiState state = guiState; + + Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height }; + + if (*active < 0) *active = 0; + else if (*active > count - 1) *active = count - 1; + + int offsetX = 0; // Required in case tabs go out of screen + offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth(); + if (offsetX < 0) offsetX = 0; + + bool toggle = false; // Required for individual toggles + + // Draw control + //-------------------------------------------------------------------- + for (int i = 0; i < count; i++) + { + tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX; + + if (tabBounds.x < GetScreenWidth()) + { + // Draw tabs as toggle controls + int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT); + int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(TOGGLE, TEXT_PADDING, 8); + + if (i == (*active)) + { + toggle = true; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + } + else + { + toggle = false; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + 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); + + // Draw tab close button + // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds)) + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i; +#else + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i; +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + } + } + + // Draw tab-bar bottom line + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL))); + //-------------------------------------------------------------------- + + return result; // Return as result the current TAB closing requested +} + +// Scroll Panel control +int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view) +{ + #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; + + Rectangle temp = { 0 }; + if (view == NULL) view = &temp; + + Vector2 scrollPos = { 0.0f, 0.0f }; + if (scroll != NULL) scrollPos = *scroll; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1; + } + + bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + + // Recheck to account for the other scrollbar being visible + if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + + int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth + }; + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Make sure scroll bars have a minimum width/height + 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)? + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + + // Clip view area to the actual content size + if (view->width > content.width) view->width = content.width; + if (view->height > content.height) view->height = content.height; + + float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH); + float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f; + float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + +#if defined(SUPPORT_SCROLLBAR_KEY_INPUT) + if (hasHorizontalScrollBar) + { + if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } + + if (hasVerticalScrollBar) + { + if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } +#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.x; + else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll + } + } + + // Normalize scroll values + if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin; + if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax; + if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin; + if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Save size of the scrollbar slider + const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + + // Draw horizontal scrollbar if visible + if (hasHorizontalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content width and the widget width + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth))); + scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax); + } + else scrollPos.x = 0.0f; + + // Draw vertical scrollbar if visible + if (hasVerticalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content height and the widget height + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth))); + scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax); + } + else scrollPos.y = 0.0f; + + // Draw detail corner rectangle if both scroll bars are visible + if (hasHorizontalScrollBar && hasVerticalScrollBar) + { + Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 }; + GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3)))); + } + + // Draw scrollbar lines depending on current state + 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); + //-------------------------------------------------------------------- + + if (scroll != NULL) *scroll = scrollPos; + + return result; +} + +// Label control +int GuiLabel(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + //... + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Button control, returns true when clicked +int GuiButton(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3)))); + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //------------------------------------------------------------------ + + return result; // Button pressed: result = 1 +} + +// Label button control +int GuiLabelButton(Rectangle bounds, const char *text) +{ + GuiState state = guiState; + bool pressed = false; + + // NOTE: We force bounds.width to be all text + float textWidth = (float)GetTextWidth(text); + if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return pressed; +} + +// Toggle Button control +int GuiToggle(Rectangle bounds, const char *text, bool *active) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (active == NULL) active = &temp; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check toggle button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_NORMAL; + *active = !(*active); + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_NORMAL) + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3))))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3))))); + } + else + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3))); + } + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; +} + +// Toggle Group control +int GuiToggleGroup(Rectangle bounds, const char *text, int *active) +{ + #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) + #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32 + #endif + + int result = 0; + float initBoundsX = bounds.x; + + int temp = 0; + if (active == NULL) active = &temp; + + bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, rows); + + int prevRow = rows[0]; + + for (int i = 0; i < itemCount; i++) + { + if (prevRow != rows[i]) + { + bounds.x = initBoundsX; + bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING)); + prevRow = rows[i]; + } + + if (i == (*active)) + { + toggle = true; + GuiToggle(bounds, items[i], &toggle); + } + else + { + toggle = false; + GuiToggle(bounds, items[i], &toggle); + if (toggle) *active = i; + } + + bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING)); + } + + return result; +} + +// Toggle Slider control extended +int GuiToggleSlider(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + //bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle slider = { + 0, // Calculated later depending on the active toggle + bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount, + bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + (*active)++; + result = 1; + } + else state = STATE_FOCUSED; + } + + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; + } + + if (*active >= itemCount) *active = 0; + slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))), + GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL))); + + // Draw internal slider + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + + // Draw text in slider + if (text != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(text); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = slider.x + slider.width/2 - textBounds.width/2; + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha)); + } + //-------------------------------------------------------------------- + + return result; +} + +// Check Box control, returns 1 when state changed +int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (checked == NULL) checked = &temp; + + 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(CHECKBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + Rectangle totalBounds = { + (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x, + bounds.y, + bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING), + bounds.height, + }; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, totalBounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + *checked = !(*checked); + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK); + + if (*checked) + { + Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)), + bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) }; + GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3))); + } + + GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Combo Box control +int GuiComboBox(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING)); + + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height }; + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + if (*active < 0) *active = 0; + else if (*active > (itemCount - 1)) *active = itemCount - 1; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds) || + CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + *active += 1; + if (*active >= itemCount) *active = 0; // Cyclic combobox + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw combo box main + GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3)))); + GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3)))); + + // Draw selector using a custom button + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount)); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + return result; +} + +// Dropdown Box control +// NOTE: Returns mouse click +int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode) +{ + 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) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (editMode) + { + state = STATE_PRESSED; + + // Check if mouse has been pressed or released outside limits + if (!CheckCollisionPointRec(mousePoint, boundsOpen)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + + // Check if already selected item has been pressed again + if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + + // Check focused and selected item + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + 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)) + { + itemFocused = i; + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + itemSelected = i; + result = 1; // Item selected + } + break; + } + } + + itemBounds = bounds; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + result = 1; + state = STATE_PRESSED; + } + else state = STATE_FOCUSED; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (editMode) GuiPanel(boundsOpen, NULL); + + GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3))); + GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3))); + + if (editMode) + { + // Draw visible items + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + 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) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED))); + } + else if (i == itemFocused) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED))); + } + else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL))); + } + } + + 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)))); +#else + 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; + + // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item... + return result; // Mouse click: result = 1 +} + +// Text Box control +// NOTE: Returns true on ENTER pressed (useful for data validation) +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 + #endif + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 1 // Frames delay for autocursor movement + #endif + + int result = 0; + GuiState state = guiState; + + bool multiline = false; // TODO: Consider multiline text input + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); + + Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); + 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 + // NOTE: Position X value should be updated + Rectangle cursor = { + textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING), + textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), + 2, + (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2 + }; + + if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH); + + // Mouse cursor rectangle + // NOTE: Initialized outside of screen + Rectangle mouseCursor = cursor; + mouseCursor.x = -1; + mouseCursor.width = 1; + + // Auto-cursor movement logic + // NOTE: Cursor moves automatically when key down after some time + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCooldownCounter++; + else + { + autoCursorCooldownCounter = 0; // GLOBAL: Cursor cooldown counter + autoCursorDelayCounter = 0; // GLOBAL: Cursor delay counter + } + + // Blink-cursor frame counter + //if (!autoCursorMode) blinkCursorFrameCounter++; + //else blinkCursorFrameCounter = 0; + + // Update control + //-------------------------------------------------------------------- + // WARNING: Text editing is only supported under certain conditions: + if ((state != STATE_DISABLED) && // Control not disabled + !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode + !guiLocked && // Gui not locked + !guiControlExclusiveMode && // No gui slider on dragging + (wrapMode == TEXT_WRAP_NONE)) // No wrap mode + { + Vector2 mousePosition = GetMousePosition(); + + if (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) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textIndexOffset, &nextCodepointSize); + + textIndexOffset += nextCodepointSize; + + textWidth = GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex); + } + + int codepoint = GetCharPressed(); // Get Unicode codepoint + if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; + + // 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) < textSize)) + { + // Move forward data from cursor position + for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; + + // Add new codepoint in current cursor position + for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i]; + + textBoxCursorIndex += codepointSize; + textLength += codepointSize; + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + + // Move cursor to start + if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0; + + // Move cursor to end + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength; + + // Delete codepoint from text, after current cursor position + if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_DELETE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + // Move backward text from cursor position + 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'; + } + } + + // Delete related codepoints from text, before current cursor position + if ((textLength > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int i = textBoxCursorIndex - 1; + int accCodepointSize = 0; + + // Move cursor to the end of word if on space already + while ((i > 0) && isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move cursor to the start of the word + while ((i > 0) && !isspace(text[i])) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + i, &prevCodepointSize); + i -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move forward text from cursor position + for (int j = (textBoxCursorIndex - accCodepointSize); j < textLength; j++) text[j] = text[j + accCodepointSize]; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + textBoxCursorIndex -= accCodepointSize; + textLength -= accCodepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + else if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_BACKSPACE) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int prevCodepointSize = 0; + + // Prevent cursor index from decrementing past 0 + if (textBoxCursorIndex > 0) + { + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move backward text from cursor position + for (int i = (textBoxCursorIndex - prevCodepointSize); i < textLength; i++) text[i] = text[i + prevCodepointSize]; + + textBoxCursorIndex -= codepointSize; + textLength -= codepointSize; + } + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + } + + // Move cursor position with keys + if (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_LEFT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int prevCodepointSize = 0; + if (textBoxCursorIndex > 0) GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + if (textBoxCursorIndex >= prevCodepointSize) textBoxCursorIndex -= prevCodepointSize; + } + } + else if (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && (autoCursorCooldownCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))) + { + autoCursorDelayCounter++; + + if (IsKeyPressed(KEY_RIGHT) || (autoCursorDelayCounter%RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0) // Delay every movement some frames + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + if ((textBoxCursorIndex + nextCodepointSize) <= textLength) textBoxCursorIndex += nextCodepointSize; + } + } + + // Move cursor position with mouse + if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text + { + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; + int codepointIndex = 0; + float glyphWidth = 0.0f; + float widthToMouseX = 0; + int mouseCursorIndex = 0; + + for (int i = textIndexOffset; i < textLength; i++) + { + codepoint = GetCodepointNext(&text[i], &codepointSize); + codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2))) + { + mouseCursor.x = textBounds.x + widthToMouseX; + mouseCursorIndex = i; + break; + } + + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + + // Check if mouse cursor is at the last position + int textEndWidth = GetTextWidth(text + textIndexOffset); + if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) + { + mouseCursor.x = textBounds.x + textEndWidth; + mouseCursorIndex = textLength; + } + + // Place cursor at required index on mouse click + if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + cursor.x = mouseCursor.x; + textBoxCursorIndex = mouseCursorIndex; + } + } + else mouseCursor.x = -1; + + // Recalculate cursor position.y depending on textBoxCursorIndex + cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GetTextWidth(text + textIndexOffset) - GetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING); + //if (multiline) cursor.y = GetTextLines() + + // Finish text editing on ENTER or mouse click outside bounds + if ((!multiline && IsKeyPressed(KEY_ENTER)) || + (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index + result = 1; + } + } + else + { + if (CheckCollisionPointRec(mousePosition, bounds)) + { + state = STATE_FOCUSED; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text + result = 1; + } + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_PRESSED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); + } + else if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED))); + } + else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK); + + // Draw text considering index offset if required + // NOTE: Text index offset depends on cursor position + GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY)) + { + //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0)) + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + + // Draw mouse position cursor (if required) + if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + } + else if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; // Mouse button pressed: result = 1 +} + +/* +// 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 textSize, bool editMode) +{ + bool pressed = false; + + GuiSetStyle(TEXTBOX, TEXT_READONLY, 1); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); + + // TODO: Implement methods to calculate cursor position properly + pressed = GuiTextBox(bounds, text, textSize, editMode); + + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); + GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); + + return pressed; +} +*/ + +// Spinner control, returns selected value +int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + int result = 1; + GuiState state = guiState; + + int tempValue = *value; + + Rectangle spinner = { bounds.x + GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING), bounds.y, + bounds.width - 2*(GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH) + GuiGetStyle(SPINNER, SPIN_BUTTON_SPACING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.y, (float)GuiGetStyle(SPINNER, SPIN_BUTTON_WIDTH), (float)bounds.height }; + + 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(SPINNER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SPINNER, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check spinner state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(leftButtonBound, "<")) tempValue--; + if (GuiButton(rightButtonBound, ">")) tempValue++; +#else + if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--; + if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++; +#endif + + if (!editMode) + { + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + result = GuiValueBox(spinner, NULL, &tempValue, minValue, maxValue, editMode); + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(SPINNER, BORDER_WIDTH)); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(SPINNER, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + *value = tempValue; + return result; +} + +// Value Box control, updates input text with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, 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, "%i", *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)) + { + textValue[keyCount] = (char)key; + keyCount++; + valueHasChanged = true; + } + } + } + + // Delete text + if (keyCount > 0) + { + if (IsKeyPressed(KEY_BACKSPACE)) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToInteger(textValue); + + // NOTE: We are not clamp values until user input finishes + //if (*value > maxValue) *value = maxValue; + //else if (*value < minValue) *value = minValue; + + 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 + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + 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; +} + +// 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; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + 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) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + 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; // 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 - bounds.x - sliderWidth/2)/(bounds.width-sliderWidth)) + minValue; + } + } + else state = STATE_FOCUSED; + } + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + } + + // Control value change check + if (oldValue == *value) result = 0; + else result = 1; + + // 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); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + + // Draw slider internal bar (depends on state) + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED))); + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(SLIDER, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Slider control extended, returns selected value and has text +int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, GuiGetStyle(SLIDER, SLIDER_WIDTH)); +} + +// Slider Bar control extended, returns selected value +int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + return GuiSliderPro(bounds, textLeft, textRight, value, minValue, maxValue, 0); +} + +// Progress Bar control extended, shows current progress value +int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + + // Progress bar + Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), + bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0, + bounds.height - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if (*value > maxValue) *value = maxValue; + + // WARNING: Working with floats could lead to rounding issues + if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue)? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f); + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK); + } + else + { + if (*value > minValue) + { + // Draw progress bar with colored border, more visual + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + } + else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + + if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + 1, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + else + { + // Draw borders not yet reached by value + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + 1, bounds.y + bounds.height - 1, bounds.width - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + } + + // Draw slider internal progress bar (depends on state) + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(PROGRESSBAR, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Status Bar control +int GuiStatusBar(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Dummy rectangle control, intended for placeholding +int GuiDummyRec(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED))); + //------------------------------------------------------------------ + + return result; +} + +// List View control +int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active) +{ + int result = 0; + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL); + + return result; +} + +// List View control with extended parameters +int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) +{ + int result = 0; + GuiState state = guiState; + + int itemFocused = (focus == NULL)? -1 : *focus; + int itemSelected = (active == NULL)? -1 : *active; + + // Check if we need a scroll bar + bool useScrollBar = false; + if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true; + + // Define base item rectangle [0] + Rectangle itemBounds = { 0 }; + itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING); + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); + if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); + + // Get items on the list + int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + if (visibleItems > count) visibleItems = count; + + int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; + if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; + int endIndex = startIndex + visibleItems; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check mouse inside list view + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Check focused and selected item + for (int i = 0; i < visibleItems; i++) + { + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = startIndex + i; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (itemSelected == (startIndex + i)) itemSelected = -1; + else itemSelected = startIndex + i; + } + break; + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + int wheelMove = (int)GetMouseWheelMove(); + startIndex -= wheelMove; + + if (startIndex < 0) startIndex = 0; + else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; + + endIndex = startIndex + visibleItems; + if (endIndex > count) endIndex = count; + } + } + else itemFocused = -1; + + // Reset item rectangle y to [0] + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // 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))); + + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED))); + } + else + { + if (((startIndex + i) == itemSelected) && (active != NULL)) + { + // Draw item selected + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED))); + } + else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned! + { + // Draw item focused + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED))); + } + else + { + // Draw item normal + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL))); + } + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + Rectangle scrollBarBounds = { + bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Calculate percentage of visible items and apply same percentage to scrollbar + float percentVisible = (float)(endIndex - startIndex)/count; + float sliderSize = bounds.height*percentVisible; + + int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size + int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed + + startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); + + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default + } + //-------------------------------------------------------------------- + + if (active != NULL) *active = itemSelected; + if (focus != NULL) *focus = itemFocused; + if (scrollIndex != NULL) *scrollIndex = startIndex; + + return result; +} + +// Color Panel control - Color (RGBA) variant. +int GuiColorPanel(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + 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. + + GuiColorPanelHSV(bounds, text, &hsv); + + // 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) + { + 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), + color->a }; + } + return result; +} + +// Color Bar Alpha control +// NOTE: Returns alpha value normalized [0..1] +int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +{ + #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE) + #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10 + #endif + + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + 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; + if (*alpha >= 1.0f) *alpha = 1.0f; + //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + + // Draw alpha bar: checked background + if (state != STATE_DISABLED) + { + int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE }; + GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f)); + } + } + + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw alpha bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Bar Hue control +// Returns hue value normalized [0..1] +// NOTE: Other similar bars (for reference): +// Color GuiColorBarSat() [WHITE->color] +// Color GuiColorBarValue() [BLACK->color], HSV/HSL +// float GuiColorBarLuminance() [BLACK->WHITE] +int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) +{ + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + 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; + if (*hue >= 359.0f) *hue = 359.0f; + + } + else state = STATE_FOCUSED; + + /*if (IsKeyDown(KEY_UP)) + { + hue -= 2.0f; + if (hue <= 0.0f) hue = 0.0f; + } + else if (IsKeyDown(KEY_DOWN)) + { + hue += 2.0f; + if (hue >= 360.0f) hue = 360.0f; + }*/ + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + // Draw hue bar:color bars + // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw hue bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Picker control +// NOTE: It's divided in multiple controls: +// Color GuiColorPanel(Rectangle bounds, Color color) +// 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; + + Color temp = { 200, 0, 0, 255 }; + if (color == NULL) color = &temp; + + GuiColorPanel(bounds, NULL, 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); + + //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); + Vector3 rgb = ConvertHSVtoRGB(hsv); + + *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a }; + + return result; +} + +// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering. +// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB. +// NOTE: It's divided in multiple controls: +// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanelHSV() size +int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + + Vector3 tempHsv = { 0 }; + + if (colorHsv == NULL) + { + const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f }; + tempHsv = ConvertRGBtoHSV(tempColor); + colorHsv = &tempHsv; + } + + GuiColorPanelHSV(bounds, NULL, colorHsv); + + const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + + GuiColorBarHue(boundsHue, NULL, &colorHsv->x); + + return result; +} + +// Color Panel control - HSV variant +int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + GuiState state = guiState; + Vector2 pickerSelector = { 0 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; + + pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation + pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value + + Vector3 maxHue = { colorHsv->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) + { + Vector2 mousePoint = GetMousePosition(); + + 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 + 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 state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // 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; +} + +// Message Box control +int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons) +{ + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT) + #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING) + #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12 + #endif + + int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + //int textWidth = GetTextWidth(message) + 2; + + Rectangle textBounds = { 0 }; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + 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 + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + + prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); + //-------------------------------------------------------------------- + + return result; +} + +// Text Input Box control, ask for text +int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive) +{ + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING) + #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_HEIGHT 26 + #endif + + // Used to enable text edit mode + // WARNING: No more than one GuiTextInputBox() should be open at the same time + static bool textEditMode = false; + + int result = -1; + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT; + + int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + + Rectangle textBounds = { 0 }; + if (message != NULL) + { + int textSize = GetTextWidth(message) + 2; + + textBounds.x = bounds.x + bounds.width/2 - textSize/2; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + textBounds.width = (float)textSize; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + } + + Rectangle textBoxBounds = { 0 }; + textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2; + if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4); + textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2; + textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + // Draw message if available + if (message != NULL) + { + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + } + + if (secretViewActive != NULL) + { + static char stars[] = "****************"; + if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height }, + ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode; + + GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive); + } + else + { + if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode; + } + + int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + if (result >= 0) textEditMode = false; + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment); + //-------------------------------------------------------------------- + + return result; // Result is the pressed button index +} + +// Grid control +// NOTE: Returns grid mouse-hover selected cell +// About drawing lines at subpixel spacing, simple put, not easy solution: +// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster +int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell) +{ + // Grid lines alpha amount + #if !defined(RAYGUI_GRID_ALPHA) + #define RAYGUI_GRID_ALPHA 0.15f + #endif + + int result = 0; + GuiState state = guiState; + + Vector2 mousePoint = GetMousePosition(); + Vector2 currentMouseCell = { -1, -1 }; + + float spaceWidth = spacing/(float)subdivs; + int linesV = (int)(bounds.width/spaceWidth) + 1; + int linesH = (int)(bounds.height/spaceWidth) + 1; + + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + // NOTE: Cell values must be the upper left of the cell the mouse is in + currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing); + currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing); + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) + { + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) + { + 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, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + } + + if (mouseCell != NULL) *mouseCell = currentMouseCell; + return result; +} + +//---------------------------------------------------------------------------------- +// Tooltip management functions +// NOTE: Tooltips requires some global variables: tooltipPtr +//---------------------------------------------------------------------------------- +// Enable gui tooltips (global state) +void GuiEnableTooltip(void) { guiTooltip = true; } + +// Disable gui tooltips (global state) +void GuiDisableTooltip(void) { guiTooltip = false; } + +// Set tooltip string +void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } + +//---------------------------------------------------------------------------------- +// Styles loading functions +//---------------------------------------------------------------------------------- + +// Load raygui style file (.rgs) +// NOTE: By default a binary file is expected, that file could contain a custom font, +// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE) +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"); + + if (rgsFile != NULL) + { + char buffer[MAX_LINE_BUFFER_SIZE] = { 0 }; + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + unsigned int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + // Style property: p + + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + GuiSetStyle(controlId, propertyId, (int)propertyValue); + + } break; + case 'f': + { + // Style font: f + + int fontSize = 0; + char charmapFileName[256] = { 0 }; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName); + + Font font = { 0 }; + int *codepoints = NULL; + int codepointCount = 0; + + if (charmapFileName[0] != '0') + { + // Load text data from file + // NOTE: Expected an UTF-8 array of codepoints, no separation + char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName)); + codepoints = LoadCodepoints(textData, &codepointCount); + UnloadFileText(textData); + } + + if (fontFileName[0] != '\0') + { + // In case a font is already loaded and it is not default internal font, unload it + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + + if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount); + else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints + } + + // If font texture not properly loaded, revert to default font and size/spacing + if (font.texture.id == 0) + { + font = GetFontDefault(); + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); + } + + UnloadCodepoints(codepoints); + + if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font); + + } break; + default: break; + } + + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile != NULL) + { + fseek(rgsFile, 0, SEEK_END); + int fileDataSize = ftell(rgsFile); + fseek(rgsFile, 0, SEEK_SET); + + if (fileDataSize > 0) + { + unsigned char *fileData = (unsigned char *)RAYGUI_MALLOC(fileDataSize*sizeof(unsigned char)); + fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile); + + GuiLoadStyleFromMemory(fileData, fileDataSize); + + RAYGUI_FREE(fileData); + } + + fclose(rgsFile); + } + } +} + +// Load style default over global style +void GuiLoadStyleDefault(void) +{ + // We set this variable first to avoid cyclic function calls + // when calling GuiSetStyle() and GuiGetStyle() + guiStyleLoaded = true; + + // Initialize default LIGHT style property values + // WARNING: Default value are applied to all controls on set but + // they can be overwritten later on for every custom control + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff); + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff); + GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff); + GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff); + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff); + GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff); + GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff); + GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff); + GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); + GuiSetStyle(DEFAULT, TEXT_PADDING, 0); + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + // Initialize default extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds + + // Initialize control-specific property values + // NOTE: Those properties are in default list but require specific values by control type + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(SLIDER, TEXT_PADDING, 4); + GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT); + GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0); + GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiSetStyle(TEXTBOX, TEXT_PADDING, 4); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(VALUEBOX, TEXT_PADDING, 0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(SPINNER, TEXT_PADDING, 0); + GuiSetStyle(SPINNER, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(STATUSBAR, TEXT_PADDING, 8); + GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + // Initialize extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(TOGGLE, GROUP_PADDING, 2); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 16); + GuiSetStyle(SLIDER, SLIDER_PADDING, 1); + GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1); + GuiSetStyle(CHECKBOX, CHECK_PADDING, 1); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2); + GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16); + GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2); + GuiSetStyle(SPINNER, SPIN_BUTTON_WIDTH, 24); + GuiSetStyle(SPINNER, SPIN_BUTTON_SPACING, 2); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12); + GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28); + GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); + GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8); + GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16); + GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2); + + if (guiFont.texture.id != GetFontDefault().texture.id) + { + // Unload previous font texture + UnloadTexture(guiFont.texture); + RL_FREE(guiFont.recs); + RL_FREE(guiFont.glyphs); + guiFont.recs = NULL; + guiFont.glyphs = NULL; + + // Setup default raylib font + guiFont = GetFontDefault(); + + // NOTE: Default raylib font character 95 is a white square + Rectangle whiteChar = guiFont.recs[95]; + + // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 }); + } +} + +// Get text with icon id prepended +// NOTE: Useful to add icons by name id (enum) instead of +// a number that can change between ricon versions +const char *GuiIconText(int iconId, const char *text) +{ +#if defined(RAYGUI_NO_ICONS) + return NULL; +#else + static char buffer[1024] = { 0 }; + static char iconBuffer[16] = { 0 }; + + if (text != NULL) + { + memset(buffer, 0, 1024); + sprintf(buffer, "#%03i#", iconId); + + for (int i = 5; i < 1024; i++) + { + buffer[i] = text[i - 5]; + if (text[i - 5] == '\0') break; + } + + return buffer; + } + else + { + sprintf(iconBuffer, "#%03i#", iconId); + + return iconBuffer; + } +#endif +} + +#if !defined(RAYGUI_NO_ICONS) +// Get full icons data pointer +unsigned int *GuiGetIcons(void) { return guiIconsPtr; } + +// Load raygui icons file (.rgi) +// NOTE: In case nameIds are required, they can be requested with loadIconsName, +// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH], +// WARNING: guiIconsName[]][] memory should be manually freed! +char **GuiLoadIcons(const char *fileName, bool loadIconsName) +{ + // Style File Structure (.rgi) + // ------------------------------------------------------ + // Offset | Size | Type | Description + // ------------------------------------------------------ + // 0 | 4 | char | Signature: "rGI " + // 4 | 2 | short | Version: 100 + // 6 | 2 | short | reserved + + // 8 | 2 | short | Num icons (N) + // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S) + + // Icons name id (32 bytes per name id) + // foreach (icon) + // { + // 12+32*i | 32 | char | Icon NameId + // } + + // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size) + // S*S pixels/32bit per unsigned int = K unsigned int per icon + // foreach (icon) + // { + // ... | K | unsigned int | Icon Data + // } + + FILE *rgiFile = fopen(fileName, "rb"); + + char **guiIconsName = NULL; + + if (rgiFile != NULL) + { + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + fread(signature, 1, 4, rgiFile); + fread(&version, sizeof(short), 1, rgiFile); + fread(&reserved, sizeof(short), 1, rgiFile); + fread(&iconCount, sizeof(short), 1, rgiFile); + fread(&iconSize, sizeof(short), 1, rgiFile); + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_MALLOC(iconCount*sizeof(char **)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_MALLOC(RAYGUI_ICON_MAX_NAME_LENGTH); + fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile); + } + } + else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR); + + // Read icons data directly over internal icons array + fread(guiIconsPtr, sizeof(unsigned int), iconCount*(iconSize*iconSize/32), rgiFile); + } + + fclose(rgiFile); + } + + return guiIconsName; +} + +// Draw selected icon using rectangles pixel-by-pixel +void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color) +{ + #define BIT_CHECK(a,b) ((a) & (1u<<(b))) + + for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++) + { + for (int k = 0; k < 32; k++) + { + if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k)) + { + #if !defined(RAYGUI_STANDALONE) + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color); + #endif + } + + if ((k == 15) || (k == 31)) y++; + } + } +} + +// Set icon drawing size +void GuiSetIconScale(int scale) +{ + if (scale >= 1) guiIconScale = scale; +} + +#endif // !RAYGUI_NO_ICONS + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- + +// Load style from memory +// WARNING: Binary files only +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + int propertyCount = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'S') && + (signature[3] == ' ')) + { + short controlId = 0; + short propertyId = 0; + unsigned int propertyValue = 0; + + for (int i = 0; i < propertyCount; i++) + { + memcpy(&controlId, fileDataPtr, sizeof(short)); + memcpy(&propertyId, fileDataPtr + 2, sizeof(short)); + memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int)); + fileDataPtr += 8; + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); + } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); + } + + // Font loading is highly dependant on raylib API to load font data and image + +#if !defined(RAYGUI_STANDALONE) + // Load custom font if available + int fontDataSize = 0; + memcpy(&fontDataSize, fileDataPtr, sizeof(int)); + fileDataPtr += 4; + + if (fontDataSize > 0) + { + Font font = { 0 }; + int fontType = 0; // 0-Normal, 1-SDF + + memcpy(&font.baseSize, fileDataPtr, sizeof(int)); + memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int)); + memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + // Load font white rectangle + Rectangle fontWhiteRec = { 0 }; + memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle)); + fileDataPtr += 16; + + // Load font image parameters + int fontImageUncompSize = 0; + int fontImageCompSize = 0; + memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int)); + memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int)); + fileDataPtr += 8; + + Image imFont = { 0 }; + imFont.mipmaps = 1; + memcpy(&imFont.width, fileDataPtr, sizeof(int)); + memcpy(&imFont.height, fileDataPtr + 4, sizeof(int)); + memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize)) + { + // Compressed font atlas image data (DEFLATE), it requires DecompressData() + int dataUncompSize = 0; + unsigned char *compData = (unsigned char *)RAYGUI_MALLOC(fontImageCompSize); + memcpy(compData, fileDataPtr, fontImageCompSize); + fileDataPtr += fontImageCompSize; + + imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize); + + // Security check, dataUncompSize must match the provided fontImageUncompSize + if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted"); + + RAYGUI_FREE(compData); + } + else + { + // Font atlas image data is not compressed + imFont.data = (unsigned char *)RAYGUI_MALLOC(fontImageUncompSize); + memcpy(imFont.data, fileDataPtr, fontImageUncompSize); + fileDataPtr += fontImageUncompSize; + } + + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + font.texture = LoadTextureFromImage(imFont); + + RAYGUI_FREE(imFont.data); + + // Validate font atlas texture was loaded correctly + if (font.texture.id != 0) + { + // Load font recs data + int recsDataSize = font.glyphCount*sizeof(Rectangle); + int recsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed recs data + memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize)) + { + // Recs data is compressed, uncompress it + unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_MALLOC(recsDataCompressedSize); + + memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize); + fileDataPtr += recsDataCompressedSize; + + int recsDataUncompSize = 0; + font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted"); + + RAYGUI_FREE(recsDataCompressed); + } + else + { + // Recs data is uncompressed + font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle)); + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle)); + fileDataPtr += sizeof(Rectangle); + } + } + + // Load font glyphs info data + int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph + int glyphsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed glyphs data + memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + // Allocate required glyphs space to fill with data + font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo)); + + if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize)) + { + // Glyphs data is compressed, uncompress it + unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_MALLOC(glyphsDataCompressedSize); + + memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize); + fileDataPtr += glyphsDataCompressedSize; + + int glyphsDataUncompSize = 0; + unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted"); + + unsigned char *glyphsDataUncompPtr = glyphsDataUncomp; + + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int)); + glyphsDataUncompPtr += 16; + } + + RAYGUI_FREE(glypsDataCompressed); + RAYGUI_FREE(glyphsDataUncomp); + } + else + { + // Glyphs data is uncompressed + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int)); + fileDataPtr += 16; + } + } + } + else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture + + GuiSetFont(font); + + // Set font texture source rectangle to be used as white texture to draw shapes + // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call + if ((fontWhiteRec.x > 0) && + (fontWhiteRec.y > 0) && + (fontWhiteRec.width > 0) && + (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec); + } +#endif + } +} + +// Gui get text width considering icon +static int GetTextWidth(const char *text) +{ + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + Vector2 textSize = { 0 }; + int textIconOffset = 0; + + if ((text != NULL) && (text[0] != '\0')) + { + if (text[0] == '#') + { + for (int i = 1; (i < 5) && (text[i] != '\0'); i++) + { + if (text[i] == '#') + { + textIconOffset = i; + break; + } + } + } + + text += textIconOffset; + + // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly + float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + + // Custom MeasureText() implementation + if ((guiFont.texture.id > 0) && (text != NULL)) + { + // Get size in bytes of text, considering end of line and line break + int size = 0; + for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++) + { + if ((text[i] != '\0') && (text[i] != '\n')) size++; + else break; + } + + float scaleFactor = fontSize/(float)guiFont.baseSize; + textSize.y = (float)guiFont.baseSize*scaleFactor; + float glyphWidth = 0.0f; + + for (int i = 0, codepointSize = 0; i < size; i += codepointSize) + { + int codepoint = GetCodepointNext(&text[i], &codepointSize); + int codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); + } + + return (int)textSize.x; +} + +// Get text bounds considering control bounds +static Rectangle GetTextBounds(int control, Rectangle bounds) +{ + Rectangle textBounds = bounds; + + textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); + textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING); + textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); + textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line! + + // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds + switch (control) + { + case COMBOBOX: + case DROPDOWNBOX: + case LISTVIEW: + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW + case SLIDER: + case CHECKBOX: + case VALUEBOX: + case SPINNER: + // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER + default: + { + // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText() + if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING); + else textBounds.x += GuiGetStyle(control, TEXT_PADDING); + } + break; + } + + return textBounds; +} + +// Get text icon if provided and move text cursor +// NOTE: We support up to 999 values for iconId +static const char *GetTextIcon(const char *text, int *iconId) +{ +#if !defined(RAYGUI_NO_ICONS) + *iconId = -1; + if (text[0] == '#') // Maybe we have an icon! + { + char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0' + + int pos = 1; + while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9')) + { + iconValue[pos - 1] = text[pos]; + pos++; + } + + if (text[pos] == '#') + { + *iconId = TextToInteger(iconValue); + + // Move text pointer after icon + // WARNING: If only icon provided, it could point to EOL character: '\0' + if (*iconId >= 0) text += (pos + 1); + } + } +#endif + + return text; +} + +// Get text divided into lines (by line-breaks '\n') +const char **GetTextLines(const char *text, int *count) +{ + #define RAYGUI_MAX_TEXT_LINES 128 + + static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; + for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings + + int textSize = (int)strlen(text); + + lines[0] = text; + int len = 0; + *count = 1; + //int lineSize = 0; // Stores current line size, not returned + + for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++) + { + if (text[i] == '\n') + { + //lineSize = len; + k++; + lines[k] = &text[i + 1]; // WARNING: next value is valid? + len = 0; + *count += 1; + } + else len++; + } + + //lines[*count - 1].size = len; + + return lines; +} + +// Get text width to next space for provided string +static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex) +{ + float width = 0; + int codepointByteCount = 0; + int codepoint = 0; + int index = 0; + float glyphWidth = 0; + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + for (int i = 0; text[i] != '\0'; i++) + { + if (text[i] != ' ') + { + codepoint = GetCodepoint(&text[i], &codepointByteCount); + index = GetGlyphIndex(guiFont, codepoint); + glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor; + width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + else + { + *nextSpaceIndex = i; + break; + } + } + + return width; +} + +// Gui draw text using default font +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint) +{ + #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect + + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + if ((text == NULL) || (text[0] == '\0')) return; // Security check + + // PROCEDURE: + // - Text is processed line per line + // - For every line, horizontal alignment is defined + // - For all text, vertical alignment is defined (multiline text only) + // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only) + + // Get text lines (using '\n' as delimiter) to be processed individually + // WARNING: We can't use GuiTextSplit() function because it can be already used + // before the GuiDrawText() call and its buffer is static, it would be overriden :( + int lineCount = 0; + const char **lines = GetTextLines(text, &lineCount); + + // Text style variables + //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); + int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL); + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing + + // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap + float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2); + float posOffsetY = 0.0f; + + for (int i = 0; i < lineCount; i++) + { + int iconId = 0; + lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor + + // 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? + int textSizeX = GetTextWidth(lines[i]); + + // If text requires an icon, add size to measure + if (iconId >= 0) + { + textSizeX += RAYGUI_ICON_SIZE*guiIconScale; + + // WARNING: If only icon provided, text could be pointing to EOF character: '\0' +#if !defined(RAYGUI_NO_ICONS) + if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING; +#endif + } + + // Check guiTextAlign global variables + switch (alignment) + { + case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break; + case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break; + case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break; + 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; + case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break; + case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + default: break; + } + + // NOTE: Make sure we get pixel-perfect coordinates, + // In case of decimals we got weird text positioning + textBoundsPosition.x = (float)((int)textBoundsPosition.x); + textBoundsPosition.y = (float)((int)textBoundsPosition.y); + //--------------------------------------------------------------------------------- + + // Draw text (with icon if available) + //--------------------------------------------------------------------------------- +#if !defined(RAYGUI_NO_ICONS) + if (iconId >= 0) + { + // 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 += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + } +#endif + // Get size in bytes of text, + // considering end of line and line break + int lineSize = 0; + 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); + int index = GetGlyphIndex(guiFont, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size + + // 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) + { + // Jump to next line if current character reach end of the box limits + 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); + + 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); + } + } + + if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint + else + { + // TODO: There are multiple types of spaces in Unicode, + // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html + if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph + { + if (wrapMode == TEXT_WRAP_NONE) + { + // Draw only required text glyphs fitting the textBounds.width + 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)); + } + } + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + { + // Draw only glyphs inside the bounds + if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + + if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + //--------------------------------------------------------------------------------- + } + +#if defined(RAYGUI_DEBUG_TEXT_BOUNDS) + GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f)); +#endif +} + +// Gui draw rectangle using default raygui plain style with borders +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color) +{ + if (color.a > 0) + { + // Draw rectangle filled with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha)); + } + + if (borderWidth > 0) + { + // Draw rectangle border lines with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + } + +#if defined(RAYGUI_DEBUG_RECS_BOUNDS) + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f)); +#endif +} + +// Draw tooltip using control bounds +static void GuiTooltip(Rectangle controlRec) +{ + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) + { + Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + + if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width); + + GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, NULL); + + int textPadding = GuiGetStyle(LABEL, TEXT_PADDING); + int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_PADDING, 0); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.f }, guiTooltipPtr); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment); + GuiSetStyle(LABEL, TEXT_PADDING, textPadding); + } +} + +// Split controls text into multiple strings +// Also check for multiple columns (required by GuiToggleGroup()) +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + // NOTE: Those definitions could be externally provided if required + + // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user + // textRow is an externally provided array of integers that stores row number for every splitted string + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 1; + + if (textRow != NULL) textRow[0] = 0; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if ((buffer[i] == delimiter) || (buffer[i] == '\n')) + { + result[counter] = buffer + i + 1; + + if (textRow != NULL) + { + if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1; + else textRow[counter] = textRow[counter - 1]; + } + + buffer[i] = '\0'; // Set an end of string at this point + + counter++; + if (counter > RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + + *count = counter; + + return result; +} + +// Convert color data from RGB to HSV +// NOTE: Color data should be passed normalized +static Vector3 ConvertRGBtoHSV(Vector3 rgb) +{ + Vector3 hsv = { 0 }; + float min = 0.0f; + float max = 0.0f; + float delta = 0.0f; + + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; + + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; + + hsv.z = max; // Value + delta = max - min; + + if (delta < 0.00001f) + { + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + if (max > 0.0f) + { + // NOTE: If max is 0, this divide would cause a crash + hsv.y = (delta/max); // Saturation + } + else + { + // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + // NOTE: Comparing float values could not work properly + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + else + { + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + } + + hsv.x *= 60.0f; // Convert to degrees + + if (hsv.x < 0.0f) hsv.x += 360.0f; + + return hsv; +} + +// Convert color data from HSV to RGB +// NOTE: Color data should be passed normalized +static Vector3 ConvertHSVtoRGB(Vector3 hsv) +{ + Vector3 rgb = { 0 }; + float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f; + long i = 0; + + // NOTE: Comparing float values could not work properly + if (hsv.y <= 0.0f) + { + rgb.x = hsv.z; + rgb.y = hsv.z; + rgb.z = hsv.z; + return rgb; + } + + hh = hsv.x; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + + i = (long)hh; + ff = hh - i; + p = hsv.z*(1.0f - hsv.y); + q = hsv.z*(1.0f - (hsv.y*ff)); + t = hsv.z*(1.0f - (hsv.y*(1.0f - ff))); + + switch (i) + { + case 0: + { + rgb.x = hsv.z; + rgb.y = t; + rgb.z = p; + } break; + case 1: + { + rgb.x = q; + rgb.y = hsv.z; + rgb.z = p; + } break; + case 2: + { + rgb.x = p; + rgb.y = hsv.z; + rgb.z = t; + } break; + case 3: + { + rgb.x = p; + rgb.y = q; + rgb.z = hsv.z; + } break; + case 4: + { + rgb.x = t; + rgb.y = p; + rgb.z = hsv.z; + } break; + case 5: + default: + { + rgb.x = hsv.z; + rgb.y = p; + rgb.z = q; + } break; + } + + return rgb; +} + +// Scroll bar control (used by GuiScrollPanel()) +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) +{ + GuiState state = guiState; + + // Is the scrollbar horizontal or vertical? + bool isVertical = (bounds.width > bounds.height)? false : true; + + // The size (width or height depending on scrollbar type) of the spinner buttons + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? + (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : + (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + + // Slider bar that moves --[///]----- + Rectangle slider = { 0 }; + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = 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){ + (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)spinnerSize, (float)spinnerSize }; + + if (isVertical) + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)), + bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), + (float)sliderSize }; + } + else // horizontal + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)), + bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + (float)sliderSize, + bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) }; + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + 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, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Handle mouse wheel + int wheel = (int)GetMouseWheelMove(); + if (wheel != 0) value += wheel; + + // Handle mouse button down + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + 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); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (!CheckCollisionPointRec(mousePoint, slider)) + { + // If click on scrollbar position but not on slider, place slider directly on that position + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + + state = STATE_PRESSED; + } + + // Keyboard control on mouse hover scrollbar + /* + if (isVertical) + { + if (IsKeyDown(KEY_DOWN)) value += 5; + else if (IsKeyDown(KEY_UP)) value -= 5; + } + else + { + if (IsKeyDown(KEY_RIGHT)) value += 5; + else if (IsKeyDown(KEY_LEFT)) value -= 5; + } + */ + } + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background + + GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background + GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar + + // Draw arrows (using icon if available) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) + { +#if defined(RAYGUI_NO_ICONS) + GuiDrawText(isVertical? "^" : "<", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText(isVertical? "v" : ">", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(isVertical? "#121#" : "#118#", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL + GuiDrawText(isVertical? "#120#" : "#119#", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL +#endif + } + //-------------------------------------------------------------------- + + return value; +} + +// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f +// WARNING: It multiplies current alpha by alpha scale factor +static Color GuiFade(Color color, float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) }; + + return result; +} + +#if defined(RAYGUI_STANDALONE) +// Returns a Color struct from hexadecimal value +static Color GetColor(int hexValue) +{ + Color color; + + color.r = (unsigned char)(hexValue >> 24) & 0xFF; + color.g = (unsigned char)(hexValue >> 16) & 0xFF; + color.b = (unsigned char)(hexValue >> 8) & 0xFF; + color.a = (unsigned char)hexValue & 0xFF; + + return color; +} + +// Returns hexadecimal value for a Color +static int ColorToInt(Color color) +{ + return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a); +} + +// Check if point is inside rectangle +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && + (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Formatting of text with variables to 'embed' +static const char *TextFormat(const char *text, ...) +{ + #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE) + #define RAYGUI_TEXTFORMAT_MAX_SIZE 256 + #endif + + static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE]; + + va_list args; + va_start(args, text); + vsprintf(buffer, text, args); + va_end(args); + + return buffer; +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + +// Split string into multiple strings +const char **TextSplit(const char *text, char delimiter, int *count) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 0; + + if (text != NULL) + { + counter = 1; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if (buffer[i] == delimiter) + { + buffer[i] = '\0'; // Set an end of string at this point + result[counter] = buffer + i + 1; + counter++; + + if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + } + + *count = counter; + return result; +} + +// Get integer value from text +// NOTE: This function replaces atoi() [stdlib.h] +static int TextToInteger(const char *text) +{ + int value = 0; + int sign = 1; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + + for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0'); + + 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) +{ + static char utf8[6] = { 0 }; + int size = 0; + + if (codepoint <= 0x7f) + { + utf8[0] = (char)codepoint; + size = 1; + } + else if (codepoint <= 0x7ff) + { + utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); + utf8[1] = (char)((codepoint & 0x3f) | 0x80); + size = 2; + } + else if (codepoint <= 0xffff) + { + utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); + utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[2] = (char)((codepoint & 0x3f) | 0x80); + size = 3; + } + else if (codepoint <= 0x10ffff) + { + utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0); + utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); + utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[3] = (char)((codepoint & 0x3f) | 0x80); + size = 4; + } + + *byteSize = size; + + return utf8; +} + +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Total number of bytes processed are returned as a parameter +// NOTE: the standard says U+FFFD should be returned in case of errors +// but that character is not supported by the default font in raylib +static int GetCodepointNext(const char *text, int *codepointSize) +{ + const char *ptr = text; + int codepoint = 0x3f; // Codepoint (defaults to '?') + *codepointSize = 1; + + // Get current codepoint and bytes processed + 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 + 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 + 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 + codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); + *codepointSize = 2; + } + else if (0x00 == (0x80 & ptr[0])) + { + // 1 byte UTF-8 codepoint + codepoint = ptr[0]; + *codepointSize = 1; + } + + return codepoint; +} +#endif // RAYGUI_STANDALONE + +#endif // RAYGUI_IMPLEMENTATION diff --git a/examples/shaders/resources/LICENSE.md b/examples/shaders/resources/LICENSE.md index 7210e34b2..078036df7 100644 --- a/examples/shaders/resources/LICENSE.md +++ b/examples/shaders/resources/LICENSE.md @@ -10,4 +10,7 @@ | space.png | ❔ | ❔ | - | | texel_checker.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [UV Checker Map Maker](http://uvchecker.byvalle.com/) | | cubicmap.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | - | -| spark_flame.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [EffectTextureMaker](https://mebiusbox.github.io/contents/EffectTextureMaker/) | \ No newline at end of file +| spark_flame.png | [@raysan5](https://github.com/raysan5) | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Made with [EffectTextureMaker](https://mebiusbox.github.io/contents/EffectTextureMaker/) | +| parrots.png | [Kodak set](http://r0k.us/graphics/kodak/) | ❔ | Original name: `kodim23.png` | +| cat.png | ❔ | ❔ | - | +| mandrill.png | ❔ | [CC0](https://creativecommons.org/publicdomain/zero/1.0/) | Mandrill (a.k.a. Baboon) | \ No newline at end of file diff --git a/examples/shaders/resources/cat.png b/examples/shaders/resources/cat.png new file mode 100644 index 0000000000000000000000000000000000000000..db56b9eadbcbe2a750734fd1bc1b5f9b416d2e95 GIT binary patch literal 388467 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

~~pm;n#;V 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

!F>hw=>_CKWxakoG~>-h5-DsFflqxUtYU2@^N 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�Jy@5uYTJft?n#27PvttQ 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

    (sMz5(2V8QvGSulXwD?IDSU?YKMqz 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 G2~7akr);bM literal 0 HcmV?d00001 diff --git a/examples/shaders/resources/shaders/glsl100/color_correction.fs b/examples/shaders/resources/shaders/glsl100/color_correction.fs new file mode 100644 index 000000000..a678c6ed2 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl100/color_correction.fs @@ -0,0 +1,34 @@ +#version 100 + +precision mediump float; + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform float contrast; +uniform float saturation; +uniform float brightness; + +void main() +{ + // Get texel color + vec4 texel = texture2D(texture0, fragTexCoord); + + // Apply contrast + texel.rgb = (texel.rgb - 0.5)*(contrast/100.0 + 1.0) + 0.5; + + // Apply brightness + texel.rgb = texel.rgb + brightness/100.0; + + // Apply saturation + float intensity = dot(texel.rgb, vec3(0.299, 0.587, 0.114)); + texel.rgb = (texel.rgb - intensity)*saturation/100.0 + texel.rgb; + + // Output resulting color + gl_FragColor = texel; +} diff --git a/examples/shaders/resources/shaders/glsl120/color_correction.fs b/examples/shaders/resources/shaders/glsl120/color_correction.fs new file mode 100644 index 000000000..520275ca4 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl120/color_correction.fs @@ -0,0 +1,31 @@ +#version 120 + +// Input vertex attributes (from vertex shader) +varying vec2 fragTexCoord; +varying vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform float contrast; +uniform float saturation; +uniform float brightness; + +void main() +{ + vec4 texel = texture2D(texture0, fragTexCoord); // Get texel color + + // Apply contrast + texel.rgb = (texel.rgb - 0.5)*(contrast/100.0 + 1.0) + 0.5; + + // Apply brightness + texel.rgb = texel.rgb + brightness/100.0; + + // Apply saturation + float intensity = dot(texel.rgb, vec3(0.299, 0.587, 0.114)); + texel.rgb = (texel.rgb - intensity)*saturation/100.0 + texel.rgb; + + // Output resulting color + gl_FragColor = texel; +} \ No newline at end of file diff --git a/examples/shaders/resources/shaders/glsl330/color_correction.fs b/examples/shaders/resources/shaders/glsl330/color_correction.fs new file mode 100644 index 000000000..c489d6df1 --- /dev/null +++ b/examples/shaders/resources/shaders/glsl330/color_correction.fs @@ -0,0 +1,34 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +uniform float contrast; +uniform float saturation; +uniform float brightness; + +// Output fragment color +out vec4 finalColor; + +void main() +{ + vec4 texel = texture(texture0, fragTexCoord); // Get texel color + + // Apply contrast + texel.rgb = (texel.rgb - 0.5f)*(contrast/100.0f + 1.0f) + 0.5f; + + // Apply brightness + texel.rgb = texel.rgb + brightness/100.0f; + + // Apply saturation + float intensity = dot(texel.rgb, vec3(0.299f, 0.587f, 0.114f)); + texel.rgb = (texel.rgb - intensity)*saturation/100.0f + texel.rgb; + + // Output resulting color + finalColor = texel; +} \ No newline at end of file diff --git a/examples/shaders/shaders_color_correction.c b/examples/shaders/shaders_color_correction.c new file mode 100644 index 000000000..8aee1d0e4 --- /dev/null +++ b/examples/shaders/shaders_color_correction.c @@ -0,0 +1,149 @@ +/******************************************************************************************* +* +* raylib [shaders] example - basic color correction +* +* Example complexity rating: [★★☆☆] 2/4 +* +* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support, +* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version +* +* Example originally created with raylib 5.6, last time updated with raylib 5.6 +* +* Example contributed by Jordi Santonja (@JordSant) +* +* 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) 2025 Jordi Santonja (@JordSant) +* +********************************************************************************************/ + +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" // Required for GUI controls + +#if defined(PLATFORM_DESKTOP) + #define GLSL_VERSION 330 +#else // PLATFORM_ANDROID, PLATFORM_WEB + #define GLSL_VERSION 100 +#endif + +#define NUMBER_TEXTURES 4 + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic color correction"); + + Texture2D texture[NUMBER_TEXTURES] = { + LoadTexture("resources/parrots.png"), + LoadTexture("resources/cat.png"), + LoadTexture("resources/mandrill.png"), + LoadTexture("resources/fudesumi.png") + }; + + Shader shdrColorCorrection = LoadShader(0, TextFormat("resources/shaders/glsl%i/color_correction.fs", GLSL_VERSION)); + + int imageIndex = 0; + + int resetButtonClicked = 0; + + float contrast = 0.0f; + float saturation = 0.0f; + float brightness = 0.0f; + + // Get shader locations + int contrastLoc = GetShaderLocation(shdrColorCorrection, "contrast"); + int saturationLoc = GetShaderLocation(shdrColorCorrection, "saturation"); + int brightnessLoc = GetShaderLocation(shdrColorCorrection, "brightness"); + + // Set shader values (they can be changed later) + SetShaderValue(shdrColorCorrection, contrastLoc, &contrast, SHADER_UNIFORM_FLOAT); + SetShaderValue(shdrColorCorrection, saturationLoc, &saturation, SHADER_UNIFORM_FLOAT); + SetShaderValue(shdrColorCorrection, brightnessLoc, &brightness, SHADER_UNIFORM_FLOAT); + + 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 + //---------------------------------------------------------------------------------- + // Select texture to draw + if (IsKeyPressed(KEY_ONE)) imageIndex = 0; + else if (IsKeyPressed(KEY_TWO)) imageIndex = 1; + else if (IsKeyPressed(KEY_THREE)) imageIndex = 2; + else if (IsKeyPressed(KEY_FOUR)) imageIndex = 3; + + // Reset values to 0 + if (IsKeyPressed(KEY_R) || resetButtonClicked) + { + contrast = 0.0f; + saturation = 0.0f; + brightness = 0.0f; + } + + // Send the values to the shader + SetShaderValue(shdrColorCorrection, contrastLoc, &contrast, SHADER_UNIFORM_FLOAT); + SetShaderValue(shdrColorCorrection, saturationLoc, &saturation, SHADER_UNIFORM_FLOAT); + SetShaderValue(shdrColorCorrection, brightnessLoc, &brightness, SHADER_UNIFORM_FLOAT); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + BeginShaderMode(shdrColorCorrection); + + DrawTexture(texture[imageIndex], 580/2 - texture[imageIndex].width/2, GetScreenHeight()/2 - texture[imageIndex].height/2, WHITE); + + EndShaderMode(); + + DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); + DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 }); + + // Draw some text + DrawText("Basic Color Correction", 585, 40, 19, GRAY); + + DrawText("Picture", 602, 75, 10, GRAY); + DrawText("Press [1] - [4] to Change Picture", 600, 230, 8, GRAY); + DrawText("Press [R] to Reset Values", 600, 250, 8, GRAY); + + // Draw GUI controls + //------------------------------------------------------------------------------ + GuiToggleGroup((Rectangle){ 645, 70, 20, 20 }, "1;2;3;4", &imageIndex); + + GuiSliderBar((Rectangle){ 645, 100, 120, 20 }, "Contrast", TextFormat("%.0f", contrast), &contrast, -100.0f, 100.0f); + GuiSliderBar((Rectangle){ 645, 130, 120, 20 }, "Saturation", TextFormat("%.0f", saturation), &saturation, -100.0f, 100.0f); + GuiSliderBar((Rectangle){ 645, 160, 120, 20 }, "Brightness", TextFormat("%.0f", brightness), &brightness, -100.0f, 100.0f); + + resetButtonClicked = GuiButton((Rectangle){ 645, 190, 40, 20 }, "Reset"); + + DrawFPS(710, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + for (int i = 0; i < NUMBER_TEXTURES; ++i) + UnloadTexture(texture[i]); + UnloadShader(shdrColorCorrection); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders/shaders_color_correction.png b/examples/shaders/shaders_color_correction.png new file mode 100644 index 0000000000000000000000000000000000000000..5bf5dcba6cbacf17e713302518dbd08fe5b73561 GIT binary patch literal 311867 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 z͝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 XWeIo9EE{+jMj_KI)y<3It|ASh4J@IGE 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

    f*6KL7FTEmd{}LI-qmu``b8V-zq;C+ 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

    EiC+z%mO1@WL+SqNkJ8$m) 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 literal 0 HcmV?d00001 diff --git a/projects/VS2022/examples/shaders_color_correction.vcxproj b/projects/VS2022/examples/shaders_color_correction.vcxproj new file mode 100644 index 000000000..520c041cb --- /dev/null +++ b/projects/VS2022/examples/shaders_color_correction.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65} + Win32Proj + shaders_color_correction + 10.0 + shaders_color_correction + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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 + + + $(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 + _CRT_SECURE_NO_WARNINGS;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) + /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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 + _CRT_SECURE_NO_WARNINGS;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 81f700bec..44ef64c34 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -397,6 +397,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_mandelbrot_set", "e EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_angle_rotation", "examples\shapes_math_angle_rotation.vcxproj", "{84DE22BB-C25F-425C-A7FE-0120CF107B83}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_color_correction", "examples\shaders_color_correction.vcxproj", "{98152EDD-7E28-4FA3-89D8-B636ED5D5F65}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4923,6 +4925,30 @@ Global {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x64.Build.0 = Release|x64 {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x86.ActiveCfg = Release|Win32 {84DE22BB-C25F-425C-A7FE-0120CF107B83}.Release|x86.Build.0 = Release|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|ARM64.Build.0 = Debug|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|x64.ActiveCfg = Debug|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|x64.Build.0 = Debug|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|x86.ActiveCfg = Debug|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Debug|x86.Build.0 = Debug|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|ARM64.ActiveCfg = Release|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|ARM64.Build.0 = Release|ARM64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x64.ActiveCfg = Release|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x64.Build.0 = Release|x64 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x86.ActiveCfg = Release|Win32 + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5123,6 +5149,7 @@ Global {2F578155-D51F-4C03-AB7F-5C5122CA46CC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {1C829D1A-892C-451C-AF0B-AC65C85F5CC6} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {84DE22BB-C25F-425C-A7FE-0120CF107B83} = {278D8859-20B1-428F-8448-064F46E1F021} + {98152EDD-7E28-4FA3-89D8-B636ED5D5F65} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} From 40594f3ec09ac1c045c112422ee4315371d99015 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sun, 26 Oct 2025 10:24:56 -0700 Subject: [PATCH 078/102] Fix typo in font loading documentation (#5308) --- examples/text/text_font_loading.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/text/text_font_loading.c b/examples/text/text_font_loading.c index f1582348b..151b63d45 100644 --- a/examples/text/text_font_loading.c +++ b/examples/text/text_font_loading.c @@ -9,7 +9,7 @@ * - TTF/OTF > Sprite font atlas is generated on loading, user can configure * some of the generation parameters (size, characters to include) * - BMFonts > Angel code font fileformat, sprite font image must be provided -* together with the .fnt file, font generation cna not be configured +* together with the .fnt file, font generation can not be configured * - XNA Spritefont > Sprite font image, following XNA Spritefont conventions, * Characters in image must follow some spacing and order rules * From 6a5b7fb3f8a7e718c91a66aa66ee2f038cb0dba6 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 18:40:46 +0100 Subject: [PATCH 079/102] Update models_decals.c --- examples/models/models_decals.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index 6fa2bd75b..d445e69cd 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -46,7 +46,7 @@ static Mesh BuildMesh(MeshBuilder *mb); static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset); static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s); #define FreeDecalMeshData() GenMeshDecal((Model){ .meshCount = -1.0f }, (Matrix){ 0 }, 0.0f, 0.0f) -static bool Button(Rectangle rec, char *label); +static bool GuiButton(Rectangle rec, const char *label); //------------------------------------------------------------------------------------ // Program main entry point @@ -248,14 +248,12 @@ int main(void) DrawText("Hold RMB to move camera", 10, 430, 10, GRAY); DrawText("(c) Character model and texture from kenney.nl", screenWidth - 260, screenHeight - 20, 10, GRAY); - Rectangle rect = (Rectangle){ 10, screenHeight - 100, 100, 60 }; + // UI elements + if (GuiButton((Rectangle){ 10, screenHeight - 100, 100, 60 }, showModel ? "Hide Model" : "Show Model")) showModel = !showModel; - if (Button(rect, showModel ? "Hide Model" : "Show Model")) showModel = !showModel; - - rect.x += rect.width + 10; - - if (Button(rect, "Clear Decals")) + if (GuiButton((Rectangle){ 10 + 110, screenHeight - 100, 100, 60 }, "Clear Decals")) { + // Clear decals, unload all decal models for (int i = 0; i < decalCount; i++) UnloadModel(decalModels[i]); decalCount = 0; } @@ -362,14 +360,14 @@ static Vector3 ClipSegment(Vector3 v0, Vector3 v1, Vector3 p, float s) } // Generate mesh decals for provided model -static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, float decalOffset) +static Mesh GenMeshDecal(Model target, Matrix projection, float decalSize, float decalOffset) { // We're going to use these to build up our decal meshes // They'll resize automatically as we go, we'll free them at the end static MeshBuilder meshBuilders[2] = { 0 }; // Ugly way of telling us to free the static MeshBuilder data - if (inputModel.meshCount == -1) + if (target.meshCount == -1) { FreeMeshBuilder(&meshBuilders[0]); FreeMeshBuilder(&meshBuilders[1]); @@ -388,9 +386,9 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f int mbIndex = 0; // First pass, just get any triangle inside the bounding box (for each mesh of the model) - for (int meshIndex = 0; meshIndex < inputModel.meshCount; meshIndex++) + for (int meshIndex = 0; meshIndex < target.meshCount; meshIndex++) { - Mesh mesh = inputModel.meshes[meshIndex]; + Mesh mesh = target.meshes[meshIndex]; for (int tri = 0; tri < mesh.triangleCount; tri++) { Vector3 vertices[3] = { 0 }; @@ -584,7 +582,7 @@ static Mesh GenMeshDecal(Model inputModel, Matrix projection, float decalSize, f } // Button UI element -static bool Button(Rectangle rec, const char *label) +static bool GuiButton(Rectangle rec, const char *label) { Color bgColor = GRAY; bool pressed = false; From a6dd08fb71f31be5e68a5fd3ab3f729c51f7a208 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 20:10:47 +0100 Subject: [PATCH 080/102] Update shaders_color_correction.c --- examples/shaders/shaders_color_correction.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/shaders/shaders_color_correction.c b/examples/shaders/shaders_color_correction.c index 8aee1d0e4..c96f606d8 100644 --- a/examples/shaders/shaders_color_correction.c +++ b/examples/shaders/shaders_color_correction.c @@ -29,7 +29,7 @@ #define GLSL_VERSION 100 #endif -#define NUMBER_TEXTURES 4 +#define MAX_TEXTURES 4 //------------------------------------------------------------------------------------ // Program main entry point @@ -43,7 +43,7 @@ int main(void) InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic color correction"); - Texture2D texture[NUMBER_TEXTURES] = { + Texture2D texture[MAX_TEXTURES] = { LoadTexture("resources/parrots.png"), LoadTexture("resources/cat.png"), LoadTexture("resources/mandrill.png"), @@ -53,7 +53,6 @@ int main(void) Shader shdrColorCorrection = LoadShader(0, TextFormat("resources/shaders/glsl%i/color_correction.fs", GLSL_VERSION)); int imageIndex = 0; - int resetButtonClicked = 0; float contrast = 0.0f; @@ -113,8 +112,8 @@ int main(void) DrawLine(580, 0, 580, GetScreenHeight(), (Color){ 218, 218, 218, 255 }); DrawRectangle(580, 0, GetScreenWidth(), GetScreenHeight(), (Color){ 232, 232, 232, 255 }); - // Draw some text - DrawText("Basic Color Correction", 585, 40, 19, GRAY); + // Draw UI info text + DrawText("Color Correction", 585, 40, 20, GRAY); DrawText("Picture", 602, 75, 10, GRAY); DrawText("Press [1] - [4] to Change Picture", 600, 230, 8, GRAY); @@ -129,6 +128,7 @@ int main(void) GuiSliderBar((Rectangle){ 645, 160, 120, 20 }, "Brightness", TextFormat("%.0f", brightness), &brightness, -100.0f, 100.0f); resetButtonClicked = GuiButton((Rectangle){ 645, 190, 40, 20 }, "Reset"); + //------------------------------------------------------------------------------ DrawFPS(710, 10); @@ -138,8 +138,7 @@ int main(void) // De-Initialization //-------------------------------------------------------------------------------------- - for (int i = 0; i < NUMBER_TEXTURES; ++i) - UnloadTexture(texture[i]); + for (int i = 0; i < MAX_TEXTURES; ++i) UnloadTexture(texture[i]); UnloadShader(shdrColorCorrection); CloseWindow(); // Close window and OpenGL context From cf9a0619ca5c6bf97fc6d8a1c9d3dc63618b0ad0 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 21:21:05 +0100 Subject: [PATCH 081/102] REXM: Validate and update examples --- examples/Makefile | 3 + examples/Makefile.Web | 23 +- examples/README.md | 14 +- examples/examples_list.txt | 3 + examples/models/models_decals.c | 2 +- examples/shaders/shaders_color_correction.c | 6 +- examples/shaders/shaders_palette_switch.c | 4 +- examples/shapes/shapes_lines_drawing.c | 2 +- examples/shapes/shapes_math_angle_rotation.c | 11 +- examples/shapes/shapes_math_sine_cosine.c | 4 +- .../VS2022/examples/models_decals.vcxproj | 569 ++++++++++++++++++ .../examples/shapes_lines_drawing.vcxproj | 569 ++++++++++++++++++ .../examples/shapes_math_sine_cosine.vcxproj | 569 ++++++++++++++++++ projects/VS2022/raylib.sln | 85 ++- tools/rexm/examples_report.md | 11 +- tools/rexm/examples_report_issues.md | 2 +- 16 files changed, 1849 insertions(+), 28 deletions(-) create mode 100644 projects/VS2022/examples/models_decals.vcxproj create mode 100644 projects/VS2022/examples/shapes_lines_drawing.vcxproj create mode 100644 projects/VS2022/examples/shapes_math_sine_cosine.vcxproj diff --git a/examples/Makefile b/examples/Makefile index c601c72b2..c8500b665 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -562,8 +562,10 @@ SHAPES = \ shapes/shapes_following_eyes \ shapes/shapes_kaleidoscope \ shapes/shapes_lines_bezier \ + shapes/shapes_lines_drawing \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_angle_rotation \ shapes/shapes_math_sine_cosine \ shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ @@ -632,6 +634,7 @@ MODELS = \ models/models_bone_socket \ models/models_box_collisions \ models/models_cubicmap_rendering \ + models/models_decals \ models/models_first_person_maze \ models/models_geometric_shapes \ models/models_heightmap_rendering \ diff --git a/examples/Makefile.Web b/examples/Makefile.Web index 99be781ac..07f8d8fb8 100644 --- a/examples/Makefile.Web +++ b/examples/Makefile.Web @@ -562,8 +562,10 @@ SHAPES = \ shapes/shapes_following_eyes \ shapes/shapes_kaleidoscope \ shapes/shapes_lines_bezier \ + shapes/shapes_lines_drawing \ shapes/shapes_logo_raylib \ shapes/shapes_logo_raylib_anim \ + shapes/shapes_math_angle_rotation \ shapes/shapes_math_sine_cosine \ shapes/shapes_mouse_trail \ shapes/shapes_pie_chart \ @@ -632,6 +634,7 @@ MODELS = \ models/models_bone_socket \ models/models_box_collisions \ models/models_cubicmap_rendering \ + models/models_decals \ models/models_first_person_maze \ models/models_geometric_shapes \ models/models_heightmap_rendering \ @@ -895,12 +898,18 @@ shapes/shapes_kaleidoscope: shapes/shapes_kaleidoscope.c shapes/shapes_lines_bezier: shapes/shapes_lines_bezier.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_lines_drawing: shapes/shapes_lines_drawing.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_logo_raylib: shapes/shapes_logo_raylib.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) shapes/shapes_logo_raylib_anim: shapes/shapes_logo_raylib_anim.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) +shapes/shapes_math_angle_rotation: shapes/shapes_math_angle_rotation.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) + shapes/shapes_math_sine_cosine: shapes/shapes_math_sine_cosine.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) @@ -1157,6 +1166,12 @@ models/models_cubicmap_rendering: models/models_cubicmap_rendering.c --preload-file models/resources/cubicmap.png@resources/cubicmap.png \ --preload-file models/resources/cubicmap_atlas.png@resources/cubicmap_atlas.png +models/models_decals: models/models_decals.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ + --preload-file models/resources/models/obj/character.obj@resources/models/obj/character.obj \ + --preload-file models/resources/models/obj/character_diffuse.png@resources/models/obj/character_diffuse.png \ + --preload-file models/resources/raylib_logo.png@resources/raylib_logo.png + models/models_first_person_maze: models/models_first_person_maze.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file models/resources/cubicmap.png@resources/cubicmap.png \ @@ -1262,13 +1277,13 @@ shaders/shaders_basic_pbr: shaders/shaders_basic_pbr.c --preload-file shaders/resources/road_mra.png@resources/road_mra.png \ --preload-file shaders/resources/road_n.png@resources/road_n.png -shapes/shapes_recursive_tree: shaders/shaders_color_correction.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ - --preload-file shaders/resources/shaders/glsl100/color_correction.fs@resources/shaders/glsl100/color_correction.fs \ +shaders/shaders_color_correction: shaders/shaders_color_correction.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ --preload-file shaders/resources/parrots.png@resources/parrots.png \ --preload-file shaders/resources/cat.png@resources/cat.png \ --preload-file shaders/resources/mandrill.png@resources/mandrill.png \ - --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png + --preload-file shaders/resources/fudesumi.png@resources/fudesumi.png \ + --preload-file shaders/resources/shaders/glsl100/color_correction.fs@resources/shaders/glsl100/color_correction.fs shaders/shaders_custom_uniform: shaders/shaders_custom_uniform.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM) \ diff --git a/examples/README.md b/examples/README.md index de28c931f..4d0b25d56 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,7 +17,7 @@ You may find it easier to use than other toolchains, especially when it comes to - `zig build [module]` to compile all examples for a module (e.g. `zig build core`) - `zig build [example]` to compile _and run_ a particular example (e.g. `zig build core_basic_window`) -## EXAMPLES COLLECTION [TOTAL: 188] +## EXAMPLES COLLECTION [TOTAL: 192] ### category: core [45] @@ -71,7 +71,7 @@ Examples using raylib[core](../src/rcore.c) platform functionality like window c | [core_clipboard_text](core/core_clipboard_text.c) | core_clipboard_text | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Robin](https://github.com/RobinsAviary) | | [core_text_file_loading](core/core_text_file_loading.c) | core_text_file_loading | ⭐☆☆☆ | 5.5 | 5.6 | [Aanjishnu Bhattacharyya](https://github.com/NimComPoo-04) | -### category: shapes [32] +### category: shapes [34] Examples using raylib shapes drawing functionality, provided by raylib [shapes](../src/rshapes.c) module. @@ -105,9 +105,12 @@ Examples using raylib shapes drawing functionality, provided by raylib [shapes]( | [shapes_pie_chart](shapes/shapes_pie_chart.c) | shapes_pie_chart | ⭐⭐⭐☆ | 5.5 | 5.6 | [Gideon Serfontein](https://github.com/GideonSerf) | | [shapes_kaleidoscope](shapes/shapes_kaleidoscope.c) | shapes_kaleidoscope | ⭐⭐☆☆ | 5.5 | 5.6 | [Hugo ARNAL](https://github.com/hugoarnal) | | [shapes_clock_of_clocks](shapes/shapes_clock_of_clocks.c) | shapes_clock_of_clocks | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [shapes_math_sine_cosine](shapes/shapes_math_sine_cosine.c) | shapes_math_sine_cosine | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | | [shapes_mouse_trail](shapes/shapes_mouse_trail.c) | shapes_mouse_trail | ⭐☆☆☆ | 5.6 | 5.6-dev | [Balamurugan R](https://github.com/Bala050814) | | [shapes_simple_particles](shapes/shapes_simple_particles.c) | shapes_simple_particles | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | | [shapes_starfield_effect](shapes/shapes_starfield_effect.c) | shapes_starfield_effect | ⭐⭐☆☆ | 5.5 | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | +| [shapes_lines_drawing](shapes/shapes_lines_drawing.c) | shapes_lines_drawing | ⭐☆☆☆ | 5.6-dev | 5.6 | [Robin](https://github.com/RobinsAviary) | +| [shapes_math_angle_rotation](shapes/shapes_math_angle_rotation.c) | shapes_math_angle_rotation | ⭐☆☆☆ | 5.6-dev | 5.6 | [Kris](https://github.com/krispy-snacc) | ### category: textures [26] @@ -164,7 +167,7 @@ Examples using raylib text functionality, including sprite fonts loading/generat | [text_inline_styling](text/text_inline_styling.c) | text_inline_styling | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Wagner Barongello](https://github.com/SultansOfCode) | | [text_words_alignment](text/text_words_alignment.c) | text_words_alignment | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | -### category: models [25] +### category: models [26] Examples using raylib models functionality, including models loading/generation and drawing, provided by raylib [models](../src/rmodels.c) module. @@ -195,6 +198,7 @@ Examples using raylib models functionality, including models loading/generation | [models_tesseract_view](models/models_tesseract_view.c) | models_tesseract_view | ⭐⭐☆☆ | 5.6-dev | 5.6-dev | [Timothy van der Valk](https://github.com/arceryz) | | [models_basic_voxel](models/models_basic_voxel.c) | models_basic_voxel | ⭐⭐☆☆ | 5.5 | 5.5 | [Tim Little](https://github.com/timlittle) | | [models_rotating_cube](models/models_rotating_cube.c) | models_rotating_cube | ⭐☆☆☆ | 5.6-dev | 5.6-dev | [Jopestpe](https://github.com/jopestpe) | +| [models_decals](models/models_decals.c) | models_decals | ⭐⭐⭐⭐️ | 5.6-dev | 5.6-dev | [JP Mortiboys](https://github.com/themushroompirates) | ### category: shaders [32] @@ -214,6 +218,8 @@ Examples using raylib shaders functionality, including shaders loading, paramete | [shaders_texture_outline](shaders/shaders_texture_outline.c) | shaders_texture_outline | ⭐⭐⭐☆ | 4.0 | 4.0 | [Serenity Skiff](https://github.com/GoldenThumbs) | | [shaders_texture_waves](shaders/shaders_texture_waves.c) | shaders_texture_waves | ⭐⭐☆☆ | 2.5 | 3.7 | [Anata](https://github.com/anatagawa) | | [shaders_julia_set](shaders/shaders_julia_set.c) | shaders_julia_set | ⭐⭐⭐☆ | 2.5 | 4.0 | [Josh Colclough](https://github.com/joshcol9232) | +| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | shaders_mandelbrot_set | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | +| [shaders_color_correction](shaders/shaders_color_correction.c) | shaders_color_correction | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | | [shaders_eratosthenes_sieve](shaders/shaders_eratosthenes_sieve.c) | shaders_eratosthenes_sieve | ⭐⭐⭐☆ | 2.5 | 4.0 | [ProfJski](https://github.com/ProfJski) | | [shaders_fog_rendering](shaders/shaders_fog_rendering.c) | shaders_fog_rendering | ⭐⭐⭐☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | | [shaders_simple_mask](shaders/shaders_simple_mask.c) | shaders_simple_mask | ⭐⭐☆☆ | 2.5 | 3.7 | [Chris Camacho](https://github.com/chriscamacho) | @@ -232,8 +238,6 @@ Examples using raylib shaders functionality, including shaders loading, paramete | [shaders_lightmap_rendering](shaders/shaders_lightmap_rendering.c) | shaders_lightmap_rendering | ⭐⭐⭐☆ | 4.5 | 4.5 | [Jussi Viitala](https://github.com/nullstare) | | [shaders_rounded_rectangle](shaders/shaders_rounded_rectangle.c) | shaders_rounded_rectangle | ⭐⭐⭐☆ | 5.5 | 5.5 | [Anstro Pleuton](https://github.com/anstropleuton) | | [shaders_depth_rendering](shaders/shaders_depth_rendering.c) | shaders_depth_rendering | ⭐⭐⭐☆ | 5.6-dev | 5.6-dev | [Luís Almeida](https://github.com/luis605) | -| [shaders_mandelbrot_set](shaders/shaders_mandelbrot_set.c) | shaders_mandelbrot_set | ⭐⭐⭐☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | -| [shaders_color_correction](shaders/shaders_color_correction.c) | shaders_color_correction | ⭐⭐☆☆ | 5.6 | 5.6 | [Jordi Santonja](https://github.com/JordSant) | ### category: audio [8] diff --git a/examples/examples_list.txt b/examples/examples_list.txt index f24cb9905..7c8709785 100644 --- a/examples/examples_list.txt +++ b/examples/examples_list.txt @@ -84,6 +84,8 @@ shapes;shapes_math_sine_cosine;★★☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe" shapes;shapes_mouse_trail;★☆☆☆;5.6;5.6-dev;2025;2025;"Balamurugan R";@Bala050814 shapes;shapes_simple_particles;★★☆☆;5.6;5.6;2025;2025;"Jordi Santonja";@JordSant shapes;shapes_starfield_effect;★★☆☆;5.5;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates +shapes;shapes_lines_drawing;★☆☆☆;5.6-dev;5.6;2025;2025;"Robin";@RobinsAviary +shapes;shapes_math_angle_rotation;★☆☆☆;5.6-dev;5.6;2025;2025;"Kris";@krispy-snacc textures;textures_logo_raylib;★☆☆☆;1.0;1.0;2014;2025;"Ramon Santamaria";@raysan5 textures;textures_srcrec_dstrec;★★★☆;1.3;1.3;2015;2025;"Ramon Santamaria";@raysan5 textures;textures_image_drawing;★★☆☆;1.4;1.4;2016;2025;"Ramon Santamaria";@raysan5 @@ -150,6 +152,7 @@ models;models_bone_socket;★★★★;4.5;4.5;2024;2025;"iP";@ipzaur models;models_tesseract_view;★★☆☆;5.6-dev;5.6-dev;2024;2025;"Timothy van der Valk";@arceryz models;models_basic_voxel;★★☆☆;5.5;5.5;2025;2025;"Tim Little";@timlittle models;models_rotating_cube;★☆☆☆;5.6-dev;5.6-dev;2025;2025;"Jopestpe";@jopestpe +models;models_decals;★★★★;5.6-dev;5.6-dev;2025;2025;"JP Mortiboys";@themushroompirates shaders;shaders_ascii_rendering;★★☆☆;5.5;5.6;2025;2025;"Maicon Santana";@maiconpintoabreu shaders;shaders_basic_lighting;★★★★;3.0;4.2;2019;2025;"Chris Camacho";@chriscamacho shaders;shaders_model_shader;★★☆☆;1.3;3.7;2014;2025;"Ramon Santamaria";@raysan5 diff --git a/examples/models/models_decals.c b/examples/models/models_decals.c index d445e69cd..f556139e1 100644 --- a/examples/models/models_decals.c +++ b/examples/models/models_decals.c @@ -4,7 +4,7 @@ * * Example complexity rating: [★★★★] 4/4 * -* Example originally created with raylib 5.6-dev +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * * Example contributed by JP Mortiboys (@themushroompirates) and reviewed by Ramon Santamaria (@raysan5) * Based on previous work by @mrdoob diff --git a/examples/shaders/shaders_color_correction.c b/examples/shaders/shaders_color_correction.c index c96f606d8..3abf29840 100644 --- a/examples/shaders/shaders_color_correction.c +++ b/examples/shaders/shaders_color_correction.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [shaders] example - basic color correction +* raylib [shaders] example - color correction * * Example complexity rating: [★★☆☆] 2/4 * @@ -9,7 +9,7 @@ * * Example originally created with raylib 5.6, last time updated with raylib 5.6 * -* Example contributed by Jordi Santonja (@JordSant) +* Example contributed by Jordi Santonja (@JordSant) 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 @@ -41,7 +41,7 @@ int main(void) const int screenWidth = 800; const int screenHeight = 450; - InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic color correction"); + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color correction"); Texture2D texture[MAX_TEXTURES] = { LoadTexture("resources/parrots.png"), diff --git a/examples/shaders/shaders_palette_switch.c b/examples/shaders/shaders_palette_switch.c index e23cad1d3..048fe7fbc 100644 --- a/examples/shaders/shaders_palette_switch.c +++ b/examples/shaders/shaders_palette_switch.c @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib [shaders] example - palette switch +* raylib [shaders] example - palette switch * * Example complexity rating: [★★★☆] 3/4 * @@ -11,7 +11,7 @@ * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * -* Example originally created with raylib 2.5, last time updated with raylib 3.7 +* Example originally created with raylib 2.5, last time updated with raylib 3.7 * * Example contributed by Marco Lizza (@MarcoLizza) and reviewed by Ramon Santamaria (@raysan5) * diff --git a/examples/shapes/shapes_lines_drawing.c b/examples/shapes/shapes_lines_drawing.c index 9347acaf3..aeaae3d45 100644 --- a/examples/shapes/shapes_lines_drawing.c +++ b/examples/shapes/shapes_lines_drawing.c @@ -11,7 +11,7 @@ * 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) 2025-2025 Robin (@RobinsAviary) +* Copyright (c) 2025 Robin (@RobinsAviary) * ********************************************************************************************/ diff --git a/examples/shapes/shapes_math_angle_rotation.c b/examples/shapes/shapes_math_angle_rotation.c index 0e4802064..f895026f5 100644 --- a/examples/shapes/shapes_math_angle_rotation.c +++ b/examples/shapes/shapes_math_angle_rotation.c @@ -1,14 +1,17 @@ /******************************************************************************************* * -* raylib [shapes] example - Math angle rotation lines +* raylib [shapes] example - math angle rotation * * Example complexity rating: [★☆☆☆] 1/4 * -* Example originally created with raylib 5.5, last time updated with raylib 5.6 +* Example originally created with raylib 5.6-dev, last time updated with raylib 5.6 * * Example contributed by Kris (@krispy-snacc) and reviewed by Ramon Santamaria (@raysan5) * -* Example licensed under an unmodified zlib/libpng license +* 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) 2025 Kris (@krispy-snacc) * ********************************************************************************************/ @@ -25,7 +28,7 @@ int main(void) const int screenWidth = 720; const int screenHeight = 400; - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - angle rotation lines"); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - math angle rotation"); SetTargetFPS(60); Vector2 center = { screenWidth / 2.0f, screenHeight / 2.0f }; diff --git a/examples/shapes/shapes_math_sine_cosine.c b/examples/shapes/shapes_math_sine_cosine.c index f61d4f548..d8d13920e 100644 --- a/examples/shapes/shapes_math_sine_cosine.c +++ b/examples/shapes/shapes_math_sine_cosine.c @@ -6,12 +6,12 @@ * * Example originally created with raylib 5.6-dev, last time updated with raylib 5.6-dev * -* Example contributed by Jopestpe (@jopestpe) +* Example contributed by Jopestpe (@jopestpe) 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) 2025-2025 Jopestpe (@jopestpe) +* Copyright (c) 2025 Jopestpe (@jopestpe) * ********************************************************************************************/ diff --git a/projects/VS2022/examples/models_decals.vcxproj b/projects/VS2022/examples/models_decals.vcxproj new file mode 100644 index 000000000..a7a5e2f2b --- /dev/null +++ b/projects/VS2022/examples/models_decals.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {028F0967-B253-45DA-B1C4-FACCE45D0D8D} + Win32Proj + models_decals + 10.0 + models_decals + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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 + + + $(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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/shapes_lines_drawing.vcxproj b/projects/VS2022/examples/shapes_lines_drawing.vcxproj new file mode 100644 index 000000000..49159676b --- /dev/null +++ b/projects/VS2022/examples/shapes_lines_drawing.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {666346D7-C84B-498D-AE17-53B20C62DB1A} + Win32Proj + shapes_lines_drawing + 10.0 + shapes_lines_drawing + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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/examples/shapes_math_sine_cosine.vcxproj b/projects/VS2022/examples/shapes_math_sine_cosine.vcxproj new file mode 100644 index 000000000..8b2457b83 --- /dev/null +++ b/projects/VS2022/examples/shapes_math_sine_cosine.vcxproj @@ -0,0 +1,569 @@ + + + + + Debug.DLL + ARM64 + + + Debug.DLL + Win32 + + + Debug.DLL + x64 + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release.DLL + ARM64 + + + Release.DLL + Win32 + + + Release.DLL + x64 + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {B7FDD40F-DDA4-468E-9C40-EEB175964A26} + Win32Proj + shapes_math_sine_cosine + 10.0 + shapes_math_sine_cosine + + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + Application + true + $(DefaultPlatformToolset) + Unicode + + + 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 + + + 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)\ + + + 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)\ + + + 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\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + WindowsLocalDebugger + + + $(SolutionDir)..\..\examples\shapes + 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;shcore.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 + 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)\ + + + + + 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 + + + + + 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 44ef64c34..c15632182 100644 --- a/projects/VS2022/raylib.sln +++ b/projects/VS2022/raylib.sln @@ -399,6 +399,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_angle_rotation" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shaders_color_correction", "examples\shaders_color_correction.vcxproj", "{98152EDD-7E28-4FA3-89D8-B636ED5D5F65}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_math_sine_cosine", "examples\shapes_math_sine_cosine.vcxproj", "{B7FDD40F-DDA4-468E-9C40-EEB175964A26}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "models_decals", "examples\models_decals.vcxproj", "{028F0967-B253-45DA-B1C4-FACCE45D0D8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shapes_lines_drawing", "examples\shapes_lines_drawing.vcxproj", "{666346D7-C84B-498D-AE17-53B20C62DB1A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug.DLL|ARM64 = Debug.DLL|ARM64 @@ -4949,6 +4955,78 @@ Global {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x64.Build.0 = Release|x64 {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x86.ActiveCfg = Release|Win32 {98152EDD-7E28-4FA3-89D8-B636ED5D5F65}.Release|x86.Build.0 = Release|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|ARM64.Build.0 = Debug|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|x64.ActiveCfg = Debug|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|x64.Build.0 = Debug|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|x86.ActiveCfg = Debug|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Debug|x86.Build.0 = Debug|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|ARM64.ActiveCfg = Release|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|ARM64.Build.0 = Release|ARM64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|x64.ActiveCfg = Release|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|x64.Build.0 = Release|x64 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|x86.ActiveCfg = Release|Win32 + {B7FDD40F-DDA4-468E-9C40-EEB175964A26}.Release|x86.Build.0 = Release|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|ARM64.Build.0 = Debug|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|x64.ActiveCfg = Debug|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|x64.Build.0 = Debug|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|x86.ActiveCfg = Debug|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Debug|x86.Build.0 = Debug|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|ARM64.ActiveCfg = Release|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|ARM64.Build.0 = Release|ARM64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|x64.ActiveCfg = Release|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|x64.Build.0 = Release|x64 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|x86.ActiveCfg = Release|Win32 + {028F0967-B253-45DA-B1C4-FACCE45D0D8D}.Release|x86.Build.0 = Release|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|ARM64.ActiveCfg = Debug.DLL|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|ARM64.Build.0 = Debug.DLL|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|x64.ActiveCfg = Debug.DLL|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|x64.Build.0 = Debug.DLL|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|x86.ActiveCfg = Debug.DLL|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug.DLL|x86.Build.0 = Debug.DLL|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|ARM64.Build.0 = Debug|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|x64.ActiveCfg = Debug|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|x64.Build.0 = Debug|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|x86.ActiveCfg = Debug|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Debug|x86.Build.0 = Debug|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|ARM64.ActiveCfg = Release.DLL|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|ARM64.Build.0 = Release.DLL|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|x64.ActiveCfg = Release.DLL|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|x64.Build.0 = Release.DLL|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|x86.ActiveCfg = Release.DLL|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release.DLL|x86.Build.0 = Release.DLL|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|ARM64.ActiveCfg = Release|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|ARM64.Build.0 = Release|ARM64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|x64.ActiveCfg = Release|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|x64.Build.0 = Release|x64 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|x86.ActiveCfg = Release|Win32 + {666346D7-C84B-498D-AE17-53B20C62DB1A}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -5116,7 +5194,7 @@ Global {C54703BF-D68A-480D-BE27-49B62E45D582} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {9CD8BCAD-F212-4BCC-BA98-899743CE3279} = {CC132A4D-D081-4C26-BFB9-AB11984054F8} {0981CA28-E4A5-4DF1-987F-A41D09131EFC} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {6B1A933E-71B8-4C1F-9E79-02D98830E671} = {278D8859-20B1-428F-8448-064F46E1F021} {6BFF72EA-7362-4A3B-B6E5-9A3655BBBDA3} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {6777EC3C-077C-42FC-B4AD-B799CE55CCE4} = {8D3C83B7-F1E0-4C2E-9E34-EE5F6AB2502A} {A61DAD9C-271C-4E95-81AA-DB4CD58564D4} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} @@ -5125,7 +5203,7 @@ Global {3B27F358-2679-4F38-B297-17B536F580BB} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {718FCBD0-591D-448C-B7D5-9F1CA8544E7B} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} {19CA0070-B4B2-4394-90B7-D0C259AA35BA} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} - {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {6C82BAAE-BDDF-457D-8FA8-7E2490B07035} + {2CCCD9E4-9058-4291-BD89-39C979F0CA1E} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} {9DB1F875-6E65-4195-B23F-ED8095C0B99C} = {278D8859-20B1-428F-8448-064F46E1F021} {52BA9067-A5FC-4CE8-82AD-7204ECFDEF9F} = {278D8859-20B1-428F-8448-064F46E1F021} {8E132D5A-2C00-48D0-8747-97E41356F26F} = {278D8859-20B1-428F-8448-064F46E1F021} @@ -5150,6 +5228,9 @@ Global {1C829D1A-892C-451C-AF0B-AC65C85F5CC6} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} {84DE22BB-C25F-425C-A7FE-0120CF107B83} = {278D8859-20B1-428F-8448-064F46E1F021} {98152EDD-7E28-4FA3-89D8-B636ED5D5F65} = {5317807F-61D4-4E0F-B6DC-2D9F12621ED9} + {B7FDD40F-DDA4-468E-9C40-EEB175964A26} = {278D8859-20B1-428F-8448-064F46E1F021} + {028F0967-B253-45DA-B1C4-FACCE45D0D8D} = {AF5BEC5C-1F2B-4DA8-B12D-D09FE569237C} + {666346D7-C84B-498D-AE17-53B20C62DB1A} = {278D8859-20B1-428F-8448-064F46E1F021} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E926C768-6307-4423-A1EC-57E95B1FAB29} diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index fcc1f8839..68efbe1ef 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -64,6 +64,7 @@ Example elements validated: | core_highdpi_testbed | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_screen_recording | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | core_clipboard_text | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| core_text_file_loading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_basic_shapes | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bouncing_ball | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_bullet_hell | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -92,6 +93,7 @@ Example elements validated: | shapes_pie_chart | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_kaleidoscope | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_clock_of_clocks | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_math_sine_cosine | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_starfield_effect | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -173,6 +175,8 @@ Example elements validated: | shaders_texture_outline | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_texture_waves | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_julia_set | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shaders_mandelbrot_set | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shaders_color_correction | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_eratosthenes_sieve | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_fog_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_simple_mask | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -204,6 +208,7 @@ Example elements validated: | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| web_basic_window | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| core_text_file_loading | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shaders_mandelbrot_set | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| web_basic_window | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| models_decals | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_lines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_math_angle_rotation | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | diff --git a/tools/rexm/examples_report_issues.md b/tools/rexm/examples_report_issues.md index 5de76a17a..8d24a251d 100644 --- a/tools/rexm/examples_report_issues.md +++ b/tools/rexm/examples_report_issues.md @@ -27,4 +27,4 @@ Example elements validated: | easings_testbed | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| web_basic_window | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| web_basic_window | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From fdc500756dad1f404356a2841b3e1cd8a14871ce Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 21:21:28 +0100 Subject: [PATCH 082/102] REXM: ADDED: More detailed log info --- tools/rexm/rexm.c | 95 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index d668655c8..41fb0cae6 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -464,12 +464,14 @@ int main(int argc, char *argv[]) // Create: raylib/examples//_example_name.png if (FileExists(TextFormat("%s/%s.png", GetDirectoryPath(inFileName), exName))) { + LOG("INFO: [%s] Copying file screenshot...\n", GetFileName(inFileName)); FileCopy(TextFormat("%s/%s.png", GetDirectoryPath(inFileName), exName), TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); } else // No screenshot available next to source file { // Copy screenshot template + LOG("WARNING: [%s] No screenshot found, using placeholder screenshot\n", GetFileName(inFileName)); FileCopy(exTemplateScreenshot, TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); } @@ -478,10 +480,13 @@ int main(int argc, char *argv[]) // Scan resources used in example to copy // NOTE: resources path will be relative to example source file directory int resPathCount = 0; + LOG("INFO: [%s] Scanning file for resources...\n", GetFileName(inFileName)); char **resPaths = ScanExampleResources(TextFormat("%s/%s.c", GetDirectoryPath(inFileName), exName), &resPathCount); if (resPathCount > 0) { + LOG("INFO: [%s] Required resources found: %i\n", GetFileName(inFileName), resPathCount); + for (int r = 0; r < resPathCount; r++) { // WARNING: Special case to consider: shaders, resource paths could use conditions: "glsl%i" @@ -494,7 +499,7 @@ int main(int argc, char *argv[]) { char *resPathUpdated = TextReplace(resPaths[r], "glsl%i", TextFormat("glsl%i", glslVer[v])); - LOG("INFO: Example resource required: %s\n", resPathUpdated); + LOG("INFO: [%s] Resource required [%i/%i]: %s\n", GetFileName(inFileName), r, resPathCount, resPathUpdated); if (FileExists(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPathUpdated))) { @@ -515,7 +520,7 @@ int main(int argc, char *argv[]) } else { - LOG("INFO: Example resource required: %s\n", resPaths[r]); + LOG("INFO: [%s] Resource required [%i/%i]: %s\n", GetFileName(inFileName), r, resPathCount, resPaths[r]); if (FileExists(TextFormat("%s/%s", GetDirectoryPath(inFileName), resPaths[r]))) { @@ -543,6 +548,8 @@ int main(int argc, char *argv[]) char *exCollectionList = LoadFileText(exCollectionFilePath); if (TextFindIndex(exCollectionList, exName) == -1) // Example not found { + LOG("INFO: [%s] Adding example to collection list (%s)\n", GetFileName(inFileName), exCategory); + char *exCollectionListUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); // Updated list copy, 2MB // Add example to the main list, by category @@ -560,9 +567,15 @@ int main(int argc, char *argv[]) // Get required example info from example file header (if provided) - // NOTE: If no example info is provided (other than category/name), just using some default values + // NOTE: Load example info from provided example header rlExampleInfo *exInfo = LoadExampleInfo(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); + LOG("INFO: [%s] Example info: \n", GetFileName(inFileName)); + LOG(" > Author: %s (@%s)\n", exInfo->author, exInfo->authorGitHub); + LOG(" > Stars: %i\n", exInfo->stars); + LOG(" > Version-Update: %s-%s\n", exInfo->verCreated, exInfo->verUpdated); + LOG(" > Created-Reviewed: %i-%i\n", exInfo->yearCreated, exInfo->yearReviewed); + // Get example difficulty stars text char starsText[16] = { 0 }; for (int i = 0; i < 4; i++) @@ -599,13 +612,14 @@ int main(int argc, char *argv[]) UnloadFileText(exCollectionList); //------------------------------------------------------------------------------------------------ - // Update: Makefile, Makefile.Web, README.md, examples.js + // Update: Metadata, Makefile, Makefile.Web, README.md, examples.js //------------------------------------------------------------------------------------------------ UpdateRequiredFiles(); //------------------------------------------------------------------------------------------------ // Create: raylib/projects/VS2022/examples/_example_name.vcxproj //------------------------------------------------------------------------------------------------ + LOG("INFO: [%s] Creating example project\n", TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); // WARNING: When adding new project a unique UUID should be assigned! FileCopy(TextFormat("%s/../projects/VS2022/examples/core_basic_window.vcxproj", exBasePath), TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); @@ -619,6 +633,7 @@ int main(int argc, char *argv[]) // we must store provided file paths because pointers will be overwriten // TODO: It seems projects are added to solution BUT not to required solution folder, // that process still requires to be done manually + LOG("INFO: [%s] Adding project to raylib solution (.sln)\n", TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); AddVSProjectToSolution(exVSProjectSolutionFile, TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName), exCategory); //------------------------------------------------------------------------------------------------ @@ -633,17 +648,21 @@ int main(int argc, char *argv[]) // WARNING 1: EMSDK_PATH must be set to proper location when calling from GitHub Actions // WARNING 2: raylib.a and raylib.web.a must be available when compiling locally #if defined(_WIN32) + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", GetFileNameWithoutExt(inFileName)); //putenv("RAYLIB_DIR=C:\\GitHub\\raylib"); - putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName)); #else + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", GetFileNameWithoutExt(inFileName)); system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exCategory, exName)); #endif // Update generated .html metadata + LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exName)); UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); // Copy results to web side + LOG("INFO: [%s] Copy example build to raylib.com\n", exName); FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName), TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exCategory, exName), @@ -732,7 +751,7 @@ int main(int argc, char *argv[]) // Recompile example (on raylib side) // WARNING: EMSDK_PATH must be set to proper location when calling from GitHub Actions #if defined(_WIN32) - putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename)); #else system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRecategory, exRename)); @@ -776,6 +795,7 @@ int main(int argc, char *argv[]) // Remove example from collection for files update //------------------------------------------------------------------------------------------------ + LOG("INFO: [%s] Removing example from collection\n", exName); char *exCollectionList = LoadFileText(exCollectionFilePath); int exIndex = TextFindIndex(exCollectionList, TextFormat("%s;%s", exCategory, exName)); if (exIndex > 0) // Example found @@ -831,22 +851,33 @@ int main(int argc, char *argv[]) // Remove: raylib/examples//_example_name.c // Remove: raylib/examples//_example_name.png + LOG("INFO: [%s] Removing example code file\n", TextFormat("%s.c", exName)); FileRemove(TextFormat("%s/%s/%s.c", exBasePath, exCategory, exName)); + LOG("INFO: [%s] Removing example screenshot file\n", TextFormat("%s.png", exName)); FileRemove(TextFormat("%s/%s/%s.png", exBasePath, exCategory, exName)); // Edit: Update required files: Makefile, Makefile.Web, README.md, examples.js UpdateRequiredFiles(); // Remove: raylib/projects/VS2022/examples/_example_name.vcxproj + LOG("INFO: [%s] Removing example project file\n", TextFormat("%s.vcxproj", exName)); FileRemove(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exName)); // Edit: raylib/projects/VS2022/raylib.sln --> Remove example project + LOG("INFO: [%s] Removing example from raylib solution (.sln)\n", exName); RemoveVSProjectFromSolution(TextFormat("%s/../projects/VS2022/raylib.sln", exBasePath), exName); + // Remove: Delete example build from local copy (if exists) + FileRemove(TextFormat("%s/%s/%s.html", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.data", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.wasm", exBasePath, exCategory, exName)); + FileRemove(TextFormat("%s/%s/%s.js", exBasePath, exCategory, exName)); + // Remove: raylib.com/examples//_example_name.html // Remove: raylib.com/examples//_example_name.data // Remove: raylib.com/examples//_example_name.wasm // Remove: raylib.com/examples//_example_name.js + LOG("INFO: [%s] Deleting example from raylib.com\n", exName); FileRemove(TextFormat("%s/%s/%s.html", exWebPath, exCategory, exName)); FileRemove(TextFormat("%s/%s/%s.data", exWebPath, exCategory, exName)); FileRemove(TextFormat("%s/%s/%s.wasm", exWebPath, exCategory, exName)); @@ -868,11 +899,10 @@ int main(int argc, char *argv[]) // Build: raylib.com/examples//_example_name.data // Build: raylib.com/examples//_example_name.wasm // Build: raylib.com/examples//_example_name.js - #if defined(_WIN32) // Set required environment variables //putenv(TextFormat("RAYLIB_DIR=%s\\..", exBasePath)); - putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); //putenv("MAKE=mingw32-make"); //ChangeDirectory(exBasePath); #endif @@ -880,22 +910,28 @@ int main(int argc, char *argv[]) { // Build example for PLATFORM_DESKTOP #if defined(_WIN32) + LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: Win32)\n", exName); system(TextFormat("mingw32-make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); #else + LOG("INFO: [%s] Building example for PLATFORM_DESKTOP (Host: POSIX)\n", exName); system(TextFormat("make -C %s %s/%s PLATFORM=PLATFORM_DESKTOP -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); #endif // Build example for PLATFORM_WEB #if defined(_WIN32) + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exName); system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); #else + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exName); system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); #endif // Update generated .html metadata + LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exRebuildList[i].name)), UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name), TextFormat("%s/%s/%s.c", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); // Copy results to web side + LOG("INFO: [%s] Copy example build to raylib.com\n", exRebuildList[i].name), FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name), TextFormat("%s/%s/%s.html", exWebPath, exRebuildList[i].category, exRebuildList[i].name)); FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exRebuildList[i].category, exRebuildList[i].name), @@ -933,10 +969,9 @@ int main(int argc, char *argv[]) VALID_INVALID_CATEGORY */ - // TODO: Log more details about the validation process - // Scan available example .c files and add to collection missing ones // NOTE: Source of truth is what we have in the examples directories (on validation/update) + LOG("INFO: Scanning available example (.c) files to be added to collection...\n"); FilePathList clist = LoadDirectoryFilesEx(exBasePath, ".c", true); char *exList = LoadFileText(exCollectionFilePath); @@ -1007,6 +1042,7 @@ int main(int argc, char *argv[]) UnloadDirectoryFiles(clist); // Check all examples in collection [examples_list.txt] -> Source of truth! + LOG("INFO: Validating examples in collection...\n"); int exCollectionCount = 0; rlExampleInfo *exCollection = LoadExamplesData(exCollectionFilePath, "ALL", false, &exCollectionCount); @@ -1016,6 +1052,8 @@ int main(int argc, char *argv[]) rlExampleInfo *exInfo = &exCollection[i]; exInfo->status = 0; + LOG("INFO: [%s] Validating example...\n", exInfo->name); + // Validate: raylib/examples//_example_name.c -> File exists? if (!FileExists(TextFormat("%s/%s/%s.c", exBasePath, exInfo->category, exInfo->name))) exInfo->status |= VALID_MISSING_C; @@ -1138,11 +1176,16 @@ int main(int argc, char *argv[]) exInfo->status |= VALID_INCONSISTENT_INFO; } + if (exInfo->status == 0) LOG("INFO: [%s] Validation result: OK", exInfo->name); + else LOG("WARNING: [%s] Validation result: ISSUES FOUND", exInfo->name); + UnloadExampleInfo(exInfoHeader); } if (opCode == OP_UPDATE) { + LOG("INFO: Updating examples with issues in collection...\n"); + // Actions to fix/review anything possible from validation results //------------------------------------------------------------------------------------------------ // Check examples "status" information @@ -1162,16 +1205,16 @@ int main(int argc, char *argv[]) // NOTE: Some examples should be excluded from VS2022 solution because // they have specific platform/linkage requirements: - if ((strcmp(exInfo->name, "core_basic_window_web") == 0) || - (strcmp(exInfo->name, "core_input_gestures_web") == 0) || - (strcmp(exInfo->name, "raylib_opengl_interop") == 0) || - (strcmp(exInfo->name, "raymath_vector_angle") == 0)) continue; + if ((strcmp(exInfo->name, "web_basic_window") == 0) || + (strcmp(exInfo->name, "raylib_opengl_interop") == 0)) continue; // Review: Add: raylib/projects/VS2022/examples/_example_name.vcxproj // Review: Add: raylib/projects/VS2022/raylib.sln // Solves: VALID_MISSING_VCXPROJ, VALID_NOT_IN_VCXSOL if (exInfo->status & VALID_MISSING_VCXPROJ) { + LOG("WARNING: [%s] Missing VS2022 project file\n", exInfo->name); + LOG("INFO: [%s.vcxproj] Creating VS2022 project file\n", exInfo->name); FileCopy(TextFormat("%s/../projects/VS2022/examples/core_basic_window.vcxproj", exBasePath), TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name)); FileTextReplace(TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name), @@ -1185,6 +1228,8 @@ int main(int argc, char *argv[]) // Add project (.vcxproj) to raylib solution (.sln) if (exInfo->status & VALID_NOT_IN_VCXSOL) { + LOG("WARNING: [%s.vcxproj] Project not included in raylib solution (.sln)\n", exInfo->name); + LOG("INFO: [%s.vcxproj] Adding project to raylib solution (.sln)\n", exInfo->name); AddVSProjectToSolution(exVSProjectSolutionFile, TextFormat("%s/../projects/VS2022/examples/%s.vcxproj", exBasePath, exInfo->name), exInfo->category); @@ -1199,19 +1244,25 @@ int main(int argc, char *argv[]) if ((strcmp(exInfo->category, "others") != 0) && // Skipping "others" category ((exInfo->status & VALID_MISSING_WEB_OUTPUT) || (exInfo->status & VALID_MISSING_WEB_METADATA))) { + LOG("WARNING: [%s] Example not available on raylib web\n", exInfo->name); + // Build example for PLATFORM_WEB #if defined(_WIN32) - putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: Win32)\n", exInfo->name); + _putenv("PATH=%PATH%;C:\\raylib\\w64devkit\\bin"); system(TextFormat("mingw32-make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name)); #else + LOG("INFO: [%s] Building example for PLATFORM_WEB (Host: POSIX)\n", exInfo->name); system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exInfo->category, exInfo->name)); #endif // Update generated .html metadata + LOG("INFO: [%s.html] Updating HTML Metadata...\n", exInfo->name); UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exInfo->category, exInfo->name), TextFormat("%s/%s/%s.c", exBasePath, exInfo->category, exInfo->name)); // Copy results to web side + LOG("INFO: [%s] Copy example build to raylib.com\n", exInfo->name); FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exInfo->category, exInfo->name), TextFormat("%s/%s/%s.html", exWebPath, exInfo->category, exInfo->name)); FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exInfo->category, exInfo->name), @@ -1228,6 +1279,8 @@ int main(int argc, char *argv[]) if (exInfo->status & VALID_INCONSISTENT_INFO) { // Update source code header info + LOG("WARNING: [%s.c] Inconsistent source code metadata\n", exInfo->name); + LOG("INFO: [%s.c] Updating source code metadata...\n", exInfo->name); UpdateSourceMetadata(TextFormat("%s/%s/%s.c", exBasePath, exInfo->category, exInfo->name), exInfo); exInfo->status &= ~VALID_INCONSISTENT_INFO; @@ -1273,6 +1326,7 @@ int main(int argc, char *argv[]) | shapes_colors_palette | ✘ | ✔ | ✘ | ✔ | ✘ | ✔ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | text_format_text | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✔ | ✘ | ✔ | ✔ | ✔ | ✔ | */ + LOG("INFO: [examples_report.md] Generating examples validation report...\n"); char *report = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); @@ -1324,6 +1378,8 @@ int main(int argc, char *argv[]) // Generate a report with only the examples missing some elements //----------------------------------------------------------------------------------------------------- + LOG("INFO: [examples_report_issues.md] Generating examples issues report...\n"); + char *reportIssues = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); repIndex = 0; @@ -1437,6 +1493,7 @@ static int UpdateRequiredFiles(void) // Edit: Example source code metadata for consistency //------------------------------------------------------------------------------------------------ + LOG("INFO: Updating all examples metadata...\n"); int exListCount = 0; rlExampleInfo *exList = LoadExamplesData(exCollectionFilePath, "ALL", true, &exListCount); for (int i = 0; i < exListCount; i++) @@ -1449,6 +1506,7 @@ static int UpdateRequiredFiles(void) // Edit: raylib/examples/Makefile --> Update from collection //------------------------------------------------------------------------------------------------ + LOG("INFO: Updating raylib/examples/Makefile\n"); char *mkText = LoadFileText(TextFormat("%s/Makefile", exBasePath)); char *mkTextUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); // Updated Makefile copy, 2MB @@ -1484,6 +1542,7 @@ static int UpdateRequiredFiles(void) // Edit: raylib/examples/Makefile.Web --> Update from collection // NOTE: We avoid the "others" category on web building //------------------------------------------------------------------------------------------------ + LOG("INFO: Updating raylib/examples/Makefile.Web\n"); char *mkwText = LoadFileText(TextFormat("%s/Makefile.Web", exBasePath)); char *mkwTextUpdated = (char *)RL_CALLOC(REXM_MAX_BUFFER_SIZE, 1); // Updated Makefile copy, 2MB @@ -1602,6 +1661,7 @@ static int UpdateRequiredFiles(void) // Edit: raylib/examples/README.md --> Update from collection //------------------------------------------------------------------------------------------------ + LOG("INFO: Updating raylib/examples/README.md\n"); // NOTE: Using [examples_list.txt] to update/regen README.md // Lines format: | 01 | [core_basic_window](core/core_basic_window.c) | core_basic_window | ⭐️☆☆☆ | 1.0 | 1.0 | [Ray](https://github.com/raysan5) | char *mdText = LoadFileText(TextFormat("%s/README.md", exBasePath)); @@ -1710,6 +1770,7 @@ static int UpdateRequiredFiles(void) // Edit: raylib.com/common/examples.js --> Update from collection // NOTE: Entries format: exampleEntry('⭐️☆☆☆' , 'core' , 'basic_window'), //------------------------------------------------------------------------------------------------ + LOG("INFO: Updating raylib.com/common/examples.js\n"); char *jsText = LoadFileText(TextFormat("%s/../common/examples.js", exWebPath)); if (!jsText) { @@ -2233,7 +2294,7 @@ static int RemoveVSProjectFromSolution(const char *slnFile, const char *exName) char uuid[38] = { 0 }; strcpy(uuid, "ABCDEF00-0123-4567-89AB-000000000012"); // Temp value int textUpdatedOfsset = 0; - int exNameLen = strlen(exName); + int exNameLen = (int)strlen(exName); for (int i = 0, index = 0; i < lineCount; i++) { @@ -2304,7 +2365,7 @@ static void UpdateSourceMetadata(const char *exSrcPath, const rlExampleInfo *inf char exNameFormated[256] = { 0 }; // Example name without category and using spaces int exNameIndex = TextFindIndex(info->name, "_"); strcpy(exNameFormated, info->name + exNameIndex + 1); - int exNameLen = strlen(exNameFormated); + int exNameLen = (int)strlen(exNameFormated); for (int i = 0; i < exNameLen; i++) { if (exNameFormated[i] == '_') exNameFormated[i] = ' '; } // Update example header title (line #3 - ALWAYS) From a0f3f07bdc01ae3a548428883fbb9a93ad28dc25 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 21:23:08 +0100 Subject: [PATCH 083/102] Update examples_report.md --- tools/rexm/examples_report.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/rexm/examples_report.md b/tools/rexm/examples_report.md index 68efbe1ef..7734a234c 100644 --- a/tools/rexm/examples_report.md +++ b/tools/rexm/examples_report.md @@ -97,6 +97,8 @@ Example elements validated: | shapes_mouse_trail | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_simple_particles | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shapes_starfield_effect | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_lines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| shapes_math_angle_rotation | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_logo_raylib | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_srcrec_dstrec | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | textures_image_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -163,6 +165,7 @@ Example elements validated: | models_tesseract_view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_basic_voxel | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | models_rotating_cube | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | +| models_decals | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_ascii_rendering | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_basic_lighting | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | shaders_model_shader | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | @@ -209,6 +212,3 @@ Example elements validated: | raylib_opengl_interop | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | | embedded_files_loading | ✔ | ❌ | ✔ | ✔ | ✔ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | web_basic_window | ✔ | ❌ | ❌ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| models_decals | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_lines_drawing | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | -| shapes_math_angle_rotation | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | From 5338e3912463d31053c69bf6fb78852cff8ade3f Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 21:23:11 +0100 Subject: [PATCH 084/102] Update rexm.c --- tools/rexm/rexm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 41fb0cae6..98134ee96 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -1176,8 +1176,8 @@ int main(int argc, char *argv[]) exInfo->status |= VALID_INCONSISTENT_INFO; } - if (exInfo->status == 0) LOG("INFO: [%s] Validation result: OK", exInfo->name); - else LOG("WARNING: [%s] Validation result: ISSUES FOUND", exInfo->name); + if (exInfo->status == 0) LOG("INFO: [%s] Validation result: OK\n", exInfo->name); + else LOG("WARNING: [%s] Validation result: ISSUES FOUND\n", exInfo->name); UnloadExampleInfo(exInfoHeader); } From aae2c4b355099968e3d8aa50a2335a5764c33b72 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 26 Oct 2025 21:25:25 +0100 Subject: [PATCH 085/102] Update rexm.c --- tools/rexm/rexm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index 98134ee96..ffd4d0457 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -1003,6 +1003,9 @@ int main(int argc, char *argv[]) if (!TextIsEqual(GetFileNameWithoutExt(clist.paths[i]), "examples_template") && (TextFindIndex(exList, GetFileNameWithoutExt(clist.paths[i])) == -1)) { + // TODO: Examples to be added in the list should be added at the end of their categories, + // not at the end of the file... + // Add example to the examples collection list // WARNING: Added to the end of the list, order must be set by users and // defines placement on raylib webpage From 9aaf120bbe624d1e873181764fa3cc3e6d821716 Mon Sep 17 00:00:00 2001 From: JordSant <77529699+JordSant@users.noreply.github.com> Date: Mon, 27 Oct 2025 00:15:59 +0100 Subject: [PATCH 086/102] [examples] Fixed spaces `shaders_mandelbrot_set` (#5310) --- examples/shaders/shaders_mandelbrot_set.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/shaders/shaders_mandelbrot_set.c b/examples/shaders/shaders_mandelbrot_set.c index a373c518a..dc592b6e4 100644 --- a/examples/shaders/shaders_mandelbrot_set.c +++ b/examples/shaders/shaders_mandelbrot_set.c @@ -69,7 +69,7 @@ int main(void) float offset[2] = { startingOffset[0], startingOffset[1] }; float zoom = startingZoom; // Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in - // The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys + // The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys #if defined(PLATFORM_DESKTOP) int maxIterations = 333; float maxIterationsMultiplier = 166.5f; @@ -134,8 +134,8 @@ int main(void) if (IsKeyPressed(KEY_F1)) showControls = !showControls; // Toggle whether or not to show controls - // Change number of max iterations with UP and DOWN keys - // WARNING: Increasing the number of max iterations greatly impacts performance + // Change number of max iterations with UP and DOWN keys + // WARNING: Increasing the number of max iterations greatly impacts performance if (IsKeyPressed(KEY_UP)) { maxIterationsMultiplier *= 1.4f; @@ -167,10 +167,10 @@ int main(void) updateShader = true; } - // In case a parameter has been changed, update the shader values + // In case a parameter has been changed, update the shader values if (updateShader) - { - // As we zoom in, increase the number of max iterations to get more detail + { + // As we zoom in, increase the number of max iterations to get more detail // Aproximate formula, but it works-ish maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier); From 5db5c9b4a16ad82be08b1f100e22fd7550ae1ac5 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 27 Oct 2025 00:20:48 +0100 Subject: [PATCH 087/102] Update rexm.c --- tools/rexm/rexm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/rexm/rexm.c b/tools/rexm/rexm.c index ffd4d0457..f45ce9be3 100644 --- a/tools/rexm/rexm.c +++ b/tools/rexm/rexm.c @@ -926,12 +926,12 @@ int main(int argc, char *argv[]) system(TextFormat("make -C %s -f Makefile.Web %s/%s PLATFORM=PLATFORM_WEB -B", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); #endif // Update generated .html metadata - LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exRebuildList[i].name)), + LOG("INFO: [%s] Updating HTML Metadata...\n", TextFormat("%s.html", exRebuildList[i].name)); UpdateWebMetadata(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name), TextFormat("%s/%s/%s.c", exBasePath, exRebuildList[i].category, exRebuildList[i].name)); // Copy results to web side - LOG("INFO: [%s] Copy example build to raylib.com\n", exRebuildList[i].name), + LOG("INFO: [%s] Copy example build to raylib.com\n", exRebuildList[i].name); FileCopy(TextFormat("%s/%s/%s.html", exBasePath, exRebuildList[i].category, exRebuildList[i].name), TextFormat("%s/%s/%s.html", exWebPath, exRebuildList[i].category, exRebuildList[i].name)); FileCopy(TextFormat("%s/%s/%s.data", exBasePath, exRebuildList[i].category, exRebuildList[i].name), From 3b6a68ba69078b021a0ff87118820f1bff8180f8 Mon Sep 17 00:00:00 2001 From: Uneven Prankster <33995085+GithubPrankster@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:12:42 -0300 Subject: [PATCH 088/102] Improve support for `PLATFORM_DESKTOP_WIN32` in src/Makefile (#5311) Co-authored-by: Uneven Prankster --- src/Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4369d8084..48ff50b30 100644 --- a/src/Makefile +++ b/src/Makefile @@ -130,7 +130,7 @@ HOST_PLATFORM_OS ?= WINDOWS PLATFORM_OS ?= WINDOWS # Determine PLATFORM_OS when required -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_WEB PLATFORM_WEB_RGFW PLATFORM_ANDROID)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_DESKTOP_WIN32 PLATFORM_WEB PLATFORM_WEB_RGFW PLATFORM_ANDROID)) # No uname.exe on MinGW!, but OS=Windows_NT on Windows! # ifeq ($(UNAME),Msys) -> Windows ifeq ($(OS),Windows_NT) @@ -252,6 +252,14 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) endif +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) + GRAPHICS ?= GRAPHICS_API_OPENGL_33 + #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering + #GRAPHICS = GRAPHICS_API_OPENGL_11 # Uncomment to use OpenGL 1.1 + #GRAPHICS = GRAPHICS_API_OPENGL_21 # Uncomment to use OpenGL 2.1 + #GRAPHICS = GRAPHICS_API_OPENGL_43 # Uncomment to use OpenGL 4.3 + #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) +endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # On DRM OpenGL ES 2.0 must be used GRAPHICS = GRAPHICS_API_OPENGL_ES2 @@ -519,7 +527,7 @@ endif #------------------------------------------------------------------------------------------------ LDFLAGS = $(CUSTOM_LDFLAGS) -L. -L$(RAYLIB_RELEASE_PATH) -ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW)) +ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW PLATFORM_DESKTOP_SDL PLATFORM_DESKTOP_RGFW PLATFORM_DESKTOP_WIN32)) ifeq ($(PLATFORM_OS),WINDOWS) ifneq ($(CC), tcc) LDFLAGS += -Wl,--out-implib,$(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME)dll.a From f4ed8fc50e9b7534cc904c4a9ea5a5fc3ac25c44 Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Tue, 28 Oct 2025 17:59:59 +0100 Subject: [PATCH 089/102] [rlsw] Simplify framebuffer logic and add blit/copy fast path (#5312) * consistency tweak * unified color and depth buffer * tweaks * review the storage of clear values + complete get/set depth value * copy/blit fast path * better simd read/write * framebuffer alignment * fix 'typo' my french slipped out --- src/external/rlsw.h | 636 ++++++++++++++++++-------------------------- 1 file changed, 257 insertions(+), 379 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index e049e707e..ba2716790 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -198,6 +198,7 @@ typedef double GLclampd; //#define GL_ATTRIB_STACK_DEPTH 0x0BB0 //#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 #define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 //#define GL_COLOR_WRITEMASK 0x0C23 //#define GL_CURRENT_INDEX 0x0B01 #define GL_CURRENT_COLOR 0x0B00 @@ -332,6 +333,7 @@ typedef double GLclampd; #define glViewport(x, y, w, h) swViewport((x), (y), (w), (h)) #define glScissor(x, y, w, h) swScissor((x), (y), (w), (h)) #define glClearColor(r, g, b, a) swClearColor((r), (g), (b), (a)) +#define glClearDepth(d) swClearDepth((d)) #define glClear(bitmask) swClear((bitmask)) #define glBlendFunc(sfactor, dfactor) swBlendFunc((sfactor), (dfactor)) #define glPolygonMode(face, mode) swPolygonMode((mode)) @@ -384,7 +386,6 @@ typedef double GLclampd; #define glBindTexture(tr, id) swBindTexture((id)) // OpenGL functions NOT IMPLEMENTED by rlsw -#define glClearDepth(X) ((void)(X)) #define glDepthMask(X) ((void)(X)) #define glColorMask(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W)) #define glPixelStorei(X,Y) ((void)(X),(void)(Y)) @@ -415,6 +416,7 @@ typedef enum { SW_VERSION = GL_VERSION, SW_EXTENSIONS = GL_EXTENSIONS, SW_COLOR_CLEAR_VALUE = GL_COLOR_CLEAR_VALUE, + SW_DEPTH_CLEAR_VALUE = GL_DEPTH_CLEAR_VALUE, SW_CURRENT_COLOR = GL_CURRENT_COLOR, SW_CURRENT_TEXTURE_COORDS = GL_CURRENT_TEXTURE_COORDS, SW_POINT_SIZE = GL_POINT_SIZE, @@ -529,7 +531,6 @@ SWAPI void swClose(void); SWAPI bool swResizeFramebuffer(int w, int h); SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels); SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels); -SWAPI void *swGetColorBuffer(int *w, int *h); SWAPI void swEnable(SWstate state); SWAPI void swDisable(SWstate state); @@ -542,6 +543,7 @@ SWAPI void swViewport(int x, int y, int width, int height); SWAPI void swScissor(int x, int y, int width, int height); SWAPI void swClearColor(float r, float g, float b, float a); +SWAPI void swClearDepth(float depth); SWAPI void swClear(uint32_t bitmask); SWAPI void swBlendFunc(SWfactor sfactor, SWfactor dfactor); @@ -608,6 +610,7 @@ SWAPI void swBindTexture(uint32_t id); #define RLSW_IMPLEMENTATION #if defined(RLSW_IMPLEMENTATION) +#include #include #include #include // Required for: floorf(), fabsf() @@ -683,66 +686,67 @@ SWAPI void swBindTexture(uint32_t id); #define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS/8) #if (SW_COLOR_BUFFER_BITS == 8) - #define COLOR_TYPE uint8_t - #define COLOR_IS_PACKED 1 - #define PACK_COLOR(r,g,b) ((((uint8_t)((r)*7+0.5f))&0x07)<<5 | (((uint8_t)((g)*7+0.5f))&0x07)<<2 | ((uint8_t)((b)*3+0.5f))&0x03) - #define UNPACK_R(p) (((p)>>5)&0x07) - #define UNPACK_G(p) (((p)>>2)&0x07) - #define UNPACK_B(p) ((p)&0x03) - #define SCALE_R(v) ((v)*255+3)/7 - #define SCALE_G(v) ((v)*255+3)/7 - #define SCALE_B(v) ((v)*255+1)/3 - #define TO_FLOAT_R(v) ((v)*(1.0f/7.0f)) - #define TO_FLOAT_G(v) ((v)*(1.0f/7.0f)) - #define TO_FLOAT_B(v) ((v)*(1.0f/3.0f)) + #define SW_COLOR_TYPE uint8_t + #define SW_COLOR_IS_PACKED 1 + #define SW_COLOR_PACK_COMP 1 + #define SW_PACK_COLOR(r,g,b) ((((uint8_t)((r)*7+0.5f))&0x07)<<5 | (((uint8_t)((g)*7+0.5f))&0x07)<<2 | ((uint8_t)((b)*3+0.5f))&0x03) + #define SW_UNPACK_R(p) (((p)>>5)&0x07) + #define SW_UNPACK_G(p) (((p)>>2)&0x07) + #define SW_UNPACK_B(p) ((p)&0x03) + #define SW_SCALE_R(v) ((v)*255+3)/7 + #define SW_SCALE_G(v) ((v)*255+3)/7 + #define SW_SCALE_B(v) ((v)*255+1)/3 + #define SW_TO_FLOAT_R(v) ((v)*(1.0f/7.0f)) + #define SW_TO_FLOAT_G(v) ((v)*(1.0f/7.0f)) + #define SW_TO_FLOAT_B(v) ((v)*(1.0f/3.0f)) #elif (SW_COLOR_BUFFER_BITS == 16) - #define COLOR_TYPE uint16_t - #define COLOR_IS_PACKED 1 - #define PACK_COLOR(r,g,b) ((((uint16_t)((r)*31+0.5f))&0x1F)<<11 | (((uint16_t)((g)*63+0.5f))&0x3F)<<5 | ((uint16_t)((b)*31+0.5f))&0x1F) - #define UNPACK_R(p) (((p)>>11)&0x1F) - #define UNPACK_G(p) (((p)>>5)&0x3F) - #define UNPACK_B(p) ((p)&0x1F) - #define SCALE_R(v) ((v)*255+15)/31 - #define SCALE_G(v) ((v)*255+31)/63 - #define SCALE_B(v) ((v)*255+15)/31 - #define TO_FLOAT_R(v) ((v)*(1.0f/31.0f)) - #define TO_FLOAT_G(v) ((v)*(1.0f/63.0f)) - #define TO_FLOAT_B(v) ((v)*(1.0f/31.0f)) + #define SW_COLOR_TYPE uint16_t + #define SW_COLOR_IS_PACKED 1 + #define SW_COLOR_PACK_COMP 1 + #define SW_PACK_COLOR(r,g,b) ((((uint16_t)((r)*31+0.5f))&0x1F)<<11 | (((uint16_t)((g)*63+0.5f))&0x3F)<<5 | ((uint16_t)((b)*31+0.5f))&0x1F) + #define SW_UNPACK_R(p) (((p)>>11)&0x1F) + #define SW_UNPACK_G(p) (((p)>>5)&0x3F) + #define SW_UNPACK_B(p) ((p)&0x1F) + #define SW_SCALE_R(v) ((v)*255+15)/31 + #define SW_SCALE_G(v) ((v)*255+31)/63 + #define SW_SCALE_B(v) ((v)*255+15)/31 + #define SW_TO_FLOAT_R(v) ((v)*(1.0f/31.0f)) + #define SW_TO_FLOAT_G(v) ((v)*(1.0f/63.0f)) + #define SW_TO_FLOAT_B(v) ((v)*(1.0f/31.0f)) #else // 32 bits - #define COLOR_TYPE uint8_t - #define COLOR_IS_PACKED 0 + #define SW_COLOR_TYPE uint8_t + #define SW_COLOR_IS_PACKED 0 + #define SW_COLOR_PACK_COMP 4 #endif #if (SW_DEPTH_BUFFER_BITS == 8) - #define DEPTH_TYPE uint8_t - #define DEPTH_IS_PACKED 1 - #define DEPTH_MAX UINT8_MAX - #define DEPTH_SCALE (1.0f/UINT8_MAX) - #define PACK_DEPTH(d) ((DEPTH_TYPE)((d)*DEPTH_MAX)) - #define UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT8_MAX + #define SW_DEPTH_SCALE (1.0f/UINT8_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) #elif (SW_DEPTH_BUFFER_BITS == 16) - #define DEPTH_TYPE uint16_t - #define DEPTH_IS_PACKED 1 - #define DEPTH_MAX UINT16_MAX - #define DEPTH_SCALE (1.0f/UINT16_MAX) - #define PACK_DEPTH(d) ((DEPTH_TYPE)((d)*DEPTH_MAX)) - #define UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE uint16_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT16_MAX + #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) #else // 24 bits - #define DEPTH_TYPE uint8_t - #define DEPTH_IS_PACKED 0 - #define DEPTH_MAX 0xFFFFFF - #define DEPTH_SCALE (1.0f/0xFFFFFF) - #define PACK_DEPTH_0(d) (((uint32_t)((d)*DEPTH_MAX)>>16)&0xFF) - #define PACK_DEPTH_1(d) (((uint32_t)((d)*DEPTH_MAX)>>8)&0xFF) - #define PACK_DEPTH_2(d) ((uint32_t)((d)*DEPTH_MAX)&0xFF) - #define UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 0 + #define SW_DEPTH_PACK_COMP 3 + #define SW_DEPTH_MAX 0xFFFFFF + #define SW_DEPTH_SCALE (1.0f/0xFFFFFF) + #define SW_PACK_DEPTH_0(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFF) + #define SW_PACK_DEPTH_1(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFF) + #define SW_PACK_DEPTH_2(d) ((uint32_t)((d)*SW_DEPTH_MAX)&0xFF) + #define SW_UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) #endif -#define GET_COLOR_PTR(ptr, offset) ((void*)((uint8_t*)(ptr) + (offset)*SW_COLOR_PIXEL_SIZE)) -#define GET_DEPTH_PTR(ptr, offset) ((void*)((uint8_t*)(ptr) + (offset)*SW_DEPTH_PIXEL_SIZE)) -#define INC_COLOR_PTR(ptr) ((ptr) = (void*)((uint8_t*)(ptr) + SW_COLOR_PIXEL_SIZE)) -#define INC_DEPTH_PTR(ptr) ((ptr) = (void*)((uint8_t*)(ptr) + SW_DEPTH_PIXEL_SIZE)) - #define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) #define SW_STATE_CHECK_EX(state, flags) (((state) & (flags)) == (flags)) @@ -809,8 +813,13 @@ typedef struct { } sw_texture_t; typedef struct { - void *color; - void *depth; + alignas(SW_COLOR_PIXEL_SIZE) + SW_COLOR_TYPE color[SW_COLOR_PACK_COMP]; + SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP]; +} sw_pixel_t; + +typedef struct { + sw_pixel_t* pixels; int width; int height; int allocSz; @@ -818,8 +827,7 @@ typedef struct { typedef struct { sw_framebuffer_t framebuffer; // Main framebuffer - float clearColor[4]; // Color used to clear the screen - float clearDepth; // Depth value used to clear the screen + sw_pixel_t clearValue; // Clear value of the framebuffer float vpCenter[2]; // Viewport center float vpHalf[2]; // Viewport half dimensions @@ -1075,30 +1083,24 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) #if defined(SW_HAS_NEON) float32x4_t values = vld1q_f32(src); float32x4_t scaled = vmulq_n_f32(values, 255.0f); - scaled = vminq_f32(vmaxq_f32(scaled, vdupq_n_f32(0.0f)), vdupq_n_f32(255.0f)); - uint32x4_t clamped = vcvtq_u32_f32(scaled); - - uint16x4_t narrow16 = vmovn_u32(clamped); - uint8x8_t narrow8 = vmovn_u16(vcombine_u16(narrow16, narrow16)); - - vst1_lane_u32((uint32_t*)dst, vreinterpret_u32_u8(narrow8), 0); + int32x4_t clamped_s32 = vcvtq_s32_f32(scaled); // f32 -> s32 (truncated) + int16x4_t narrow16_s = vqmovn_s32(clamped_s32); + int16x8_t combined16_s = vcombine_s16(narrow16_s, narrow16_s); + uint8x8_t narrow8_u = vqmovun_s16(combined16_s); + vst1_lane_u32((uint32_t*)dst, vreinterpret_u32_u8(narrow8_u), 0); #elif defined(SW_HAS_SSE41) __m128 values = _mm_loadu_ps(src); __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); - scaled = _mm_max_ps(_mm_min_ps(scaled, _mm_set1_ps(255.0f)), _mm_setzero_ps()); - __m128i clamped = _mm_cvtps_epi32(scaled); - - clamped = _mm_packus_epi32(clamped, clamped); - clamped = _mm_packus_epi16(clamped, clamped); + __m128i clamped = _mm_cvtps_epi32(scaled); // f32 -> s32 (truncated) + clamped = _mm_packus_epi32(clamped, clamped); // s32 -> u16 (saturated < 0 to 0) + clamped = _mm_packus_epi16(clamped, clamped); // u16 -> u8 (saturated > 255 to 255) *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); #elif defined(SW_HAS_SSE2) __m128 values = _mm_loadu_ps(src); __m128 scaled = _mm_mul_ps(values, _mm_set1_ps(255.0f)); - scaled = _mm_max_ps(_mm_min_ps(scaled, _mm_set1_ps(255.0f)), _mm_setzero_ps()); - __m128i clamped = _mm_cvtps_epi32(scaled); - - clamped = _mm_packs_epi32(clamped, clamped); - clamped = _mm_packus_epi16(clamped, clamped); + __m128i clamped = _mm_cvtps_epi32(scaled); // f32 -> s32 (truncated) + clamped = _mm_packs_epi32(clamped, clamped); // s32 -> s16 (saturated) + clamped = _mm_packus_epi16(clamped, clamped); // s16 -> u8 (saturated < 0 to 0) *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); #else for (int i = 0; i < 4; i++) @@ -1106,7 +1108,7 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) float val = src[i]*255.0f; val = (val > 255.0f)? 255.0f : val; val = (val < 0.0f)? 0.0f : val; - dst[i] = (uint8_t)(val + 0.5f); + dst[i] = (uint8_t)val; } #endif } @@ -1114,13 +1116,9 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) { #if defined(SW_HAS_NEON) - uint32x4_t bytes = vdupq_n_u32(0); - bytes = vld1q_lane_u32((const uint32_t*)src, bytes, 0); - - uint8x8_t bytes8 = vreinterpret_u8_u32(vget_low_u32(bytes)); + uint8x8_t bytes8 = vld1_u8(src); //< Read 8 bytes, faster, but let's hope we're not at the end of the page (unlikely)... uint16x8_t bytes16 = vmovl_u8(bytes8); uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16)); - float32x4_t floats = vcvtq_f32_u32(ints); floats = vmulq_n_f32(floats, SW_INV_255); vst1q_f32(dst, floats); @@ -1204,15 +1202,8 @@ static inline bool sw_framebuffer_load(int w, int h) { int size = w*h; - RLSW.framebuffer.color = SW_MALLOC(SW_COLOR_PIXEL_SIZE*size); - if (RLSW.framebuffer.color == NULL) return false; - - RLSW.framebuffer.depth = SW_MALLOC(SW_DEPTH_PIXEL_SIZE*size); - if (RLSW.framebuffer.depth == NULL) - { - SW_FREE(RLSW.framebuffer.color); - return false; - } + RLSW.framebuffer.pixels = SW_MALLOC(sizeof(sw_pixel_t)*size); + if (RLSW.framebuffer.pixels == NULL) return false; RLSW.framebuffer.width = w; RLSW.framebuffer.height = h; @@ -1232,18 +1223,10 @@ static inline bool sw_framebuffer_resize(int w, int h) return true; } - void *newColor = SW_REALLOC(RLSW.framebuffer.color, SW_COLOR_PIXEL_SIZE*newSize); - if (newColor == NULL) return false; + void *newPixels = SW_REALLOC(RLSW.framebuffer.pixels, sizeof(sw_pixel_t)*newSize); + if (newPixels == NULL) return false; - void *newDepth = SW_REALLOC(RLSW.framebuffer.depth, SW_DEPTH_PIXEL_SIZE*newSize); - if (newDepth == NULL) - { - SW_FREE(newColor); - return false; - } - - RLSW.framebuffer.color = newColor; - RLSW.framebuffer.depth = newDepth; + RLSW.framebuffer.pixels = newPixels; RLSW.framebuffer.width = w; RLSW.framebuffer.height = h; @@ -1252,29 +1235,29 @@ static inline bool sw_framebuffer_resize(int w, int h) return true; } -static inline void sw_framebuffer_read_color(float dst[4], const void *src) +static inline void sw_framebuffer_read_color(float dst[4], const sw_pixel_t *src) { -#if COLOR_IS_PACKED - COLOR_TYPE pixel = ((COLOR_TYPE*)src)[0]; - dst[0] = TO_FLOAT_R(UNPACK_R(pixel)); - dst[1] = TO_FLOAT_G(UNPACK_G(pixel)); - dst[2] = TO_FLOAT_B(UNPACK_B(pixel)); +#if SW_COLOR_IS_PACKED + SW_COLOR_TYPE pixel = src->color[0]; + dst[0] = SW_TO_FLOAT_R(SW_UNPACK_R(pixel)); + dst[1] = SW_TO_FLOAT_G(SW_UNPACK_G(pixel)); + dst[2] = SW_TO_FLOAT_B(SW_UNPACK_B(pixel)); dst[3] = 1.0f; #else - sw_float_from_unorm8_simd(dst, src); + sw_float_from_unorm8_simd(dst, src->color); #endif } -static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src) +static inline void sw_framebuffer_read_color8(uint8_t dst[4], const sw_pixel_t *src) { -#if COLOR_IS_PACKED - COLOR_TYPE pixel = ((COLOR_TYPE*)src)[0]; - dst[0] = SCALE_R(UNPACK_R(pixel)); - dst[1] = SCALE_G(UNPACK_G(pixel)); - dst[2] = SCALE_B(UNPACK_B(pixel)); +#if SW_COLOR_IS_PACKED + SW_COLOR_TYPE pixel = src->color[0]; + dst[0] = SW_SCALE_R(SW_UNPACK_R(pixel)); + dst[1] = SW_SCALE_G(SW_UNPACK_G(pixel)); + dst[2] = SW_SCALE_B(SW_UNPACK_B(pixel)); dst[3] = 255; #else - const COLOR_TYPE *p = (const COLOR_TYPE*)src; + const SW_COLOR_TYPE *p = src->color; dst[0] = p[0]; dst[1] = p[1]; dst[2] = p[2]; @@ -1282,231 +1265,139 @@ static inline void sw_framebuffer_read_color8(uint8_t dst[4], const void *src) #endif } -static inline void sw_framebuffer_write_color(void *dst, const float src[4]) +static inline float sw_framebuffer_read_depth(const sw_pixel_t *src) { -#if COLOR_IS_PACKED - ((COLOR_TYPE*)dst)[0] = PACK_COLOR(src[0], src[1], src[2]); +#if SW_DEPTH_IS_PACKED + return src->depth[0]*SW_DEPTH_SCALE; #else - sw_float_to_unorm8_simd(dst, src); + return SW_UNPACK_DEPTH(src->depth)*SW_DEPTH_SCALE; #endif } -static inline void sw_framebuffer_fill_color(void *ptr, int size, const float color[4]) +static inline void sw_framebuffer_write_color(sw_pixel_t *dst, const float src[4]) { -#if COLOR_IS_PACKED - COLOR_TYPE packed = PACK_COLOR(color[0], color[1], color[2]); - COLOR_TYPE *p = (COLOR_TYPE*)ptr; +#if SW_COLOR_IS_PACKED + dst->color[0] = SW_PACK_COLOR(src[0], src[1], src[2]); #else - COLOR_TYPE r = sw_clampi(color[0]*255, 0, 255); - COLOR_TYPE g = sw_clampi(color[1]*255, 0, 255); - COLOR_TYPE b = sw_clampi(color[2]*255, 0, 255); - COLOR_TYPE a = sw_clampi(color[3]*255, 0, 255); - COLOR_TYPE *p = (COLOR_TYPE*)ptr; + sw_float_to_unorm8_simd(dst->color, src); #endif - +} + +static inline void sw_framebuffer_write_depth(sw_pixel_t *dst, float depth) +{ +#if SW_DEPTH_IS_PACKED + dst->depth[0] = SW_PACK_DEPTH(depth); +#else + dst->depth[0] = SW_PACK_DEPTH_0(depth); + dst->depth[1] = SW_PACK_DEPTH_1(depth); + dst->depth[2] = SW_PACK_DEPTH_2(depth); +#endif +} + +static inline void sw_framebuffer_fill_color(sw_pixel_t *ptr, int size, const SW_COLOR_TYPE color[SW_COLOR_PACK_COMP]) +{ if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) { int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) { -#if COLOR_IS_PACKED - COLOR_TYPE *row = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int x = 0; x < w; x++) *row++ = packed; -#else - COLOR_TYPE *row = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); - for (int x = 0; x < w; x++) + sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0]; + for (int x = 0; x < w; x++, row++) { - *row++ = r; - *row++ = g; - *row++ = b; - *row++ = a; + for (int i = 0; i < SW_COLOR_PACK_COMP; i++) row->color[i] = color[i]; } -#endif } } else { -#if COLOR_IS_PACKED - for (int i = 0; i < size; i++) *p++ = packed; -#else - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++, ptr++) { - *p++ = r; - *p++ = g; - *p++ = b; - *p++ = a; + for (int j = 0; j < SW_COLOR_PACK_COMP; j++) ptr->color[j] = color[j]; } -#endif } } -static inline float sw_framebuffer_read_depth(const void *src) +static inline void sw_framebuffer_fill_depth(sw_pixel_t *ptr, int size, const SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP]) { -#if DEPTH_IS_PACKED - return ((DEPTH_TYPE*)src)[0]*DEPTH_SCALE; -#else - const DEPTH_TYPE *p = (const DEPTH_TYPE*)src; - uint32_t d = UNPACK_DEPTH(p); - return d*DEPTH_SCALE; -#endif -} - -static inline void sw_framebuffer_write_depth(void *dst, float depth) -{ -#if DEPTH_IS_PACKED - ((DEPTH_TYPE*)dst)[0] = PACK_DEPTH(depth); -#else - DEPTH_TYPE *p = (DEPTH_TYPE*)dst; - p[0] = PACK_DEPTH_0(depth); - p[1] = PACK_DEPTH_1(depth); - p[2] = PACK_DEPTH_2(depth); -#endif -} - -static inline void sw_framebuffer_fill_depth(void *ptr, int size, float value) -{ -#if DEPTH_IS_PACKED - DEPTH_TYPE d = PACK_DEPTH(value); - DEPTH_TYPE *p = (DEPTH_TYPE*)ptr; -#else - DEPTH_TYPE d0 = PACK_DEPTH_0(value); - DEPTH_TYPE d1 = PACK_DEPTH_1(value); - DEPTH_TYPE d2 = PACK_DEPTH_2(value); - DEPTH_TYPE *p = (DEPTH_TYPE*)ptr; -#endif - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) { int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) { -#if DEPTH_IS_PACKED - DEPTH_TYPE *row = p + y*RLSW.framebuffer.width + RLSW.scMin[0]; - for (int x = 0; x < w; x++) *row++ = d; -#else - DEPTH_TYPE *row = p + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); - for (int x = 0; x < w; x++) + sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0]; + for (int x = 0; x < w; x++, row++) { - *row++ = d0; - *row++ = d1; - *row++ = d2; + for (int i = 0; i < SW_DEPTH_PACK_COMP; i++) row->depth[i] = depth[i]; } -#endif } } else { -#if DEPTH_IS_PACKED - for (int i = 0; i < size; i++) *p++ = d; -#else - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++, ptr++) { - *p++ = d0; - *p++ = d1; - *p++ = d2; + for (int j = 0; j < SW_DEPTH_PACK_COMP; j++) ptr->depth[j] = depth[j]; } -#endif } } -static inline void sw_framebuffer_fill(void *colorPtr, void *depthPtr, int size, float color[4], float depth) +static inline void sw_framebuffer_fill(sw_pixel_t *ptr, int size, sw_pixel_t value) { -#if COLOR_IS_PACKED - COLOR_TYPE packedColor = PACK_COLOR(color[0], color[1], color[2]); - COLOR_TYPE *pColor = (COLOR_TYPE*)colorPtr; -#else - COLOR_TYPE r = sw_clampi(color[0]*255, 0, 255); - COLOR_TYPE g = sw_clampi(color[1]*255, 0, 255); - COLOR_TYPE b = sw_clampi(color[2]*255, 0, 255); - COLOR_TYPE a = sw_clampi(color[3]*255, 0, 255); - COLOR_TYPE *pColor = (COLOR_TYPE*)colorPtr; -#endif - -#if DEPTH_IS_PACKED - DEPTH_TYPE d = PACK_DEPTH(depth); - DEPTH_TYPE *pDepth = (DEPTH_TYPE*)depthPtr; -#else - DEPTH_TYPE d0 = PACK_DEPTH_0(depth); - DEPTH_TYPE d1 = PACK_DEPTH_1(depth); - DEPTH_TYPE d2 = PACK_DEPTH_2(depth); - DEPTH_TYPE *pDepth = (DEPTH_TYPE*)depthPtr; -#endif - if (RLSW.stateFlags & SW_STATE_SCISSOR_TEST) { int w = RLSW.scMax[0] - RLSW.scMin[0] + 1; for (int y = RLSW.scMin[1]; y <= RLSW.scMax[1]; y++) { -#if COLOR_IS_PACKED - COLOR_TYPE *rowColor = pColor + y*RLSW.framebuffer.width + RLSW.scMin[0]; -#else - COLOR_TYPE *rowColor = pColor + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); -#endif - -#if DEPTH_IS_PACKED - DEPTH_TYPE *rowDepth = pDepth + y*RLSW.framebuffer.width + RLSW.scMin[0]; -#else - DEPTH_TYPE *rowDepth = pDepth + 3*(y*RLSW.framebuffer.width + RLSW.scMin[0]); -#endif - - for (int x = 0; x < w; x++) - { -#if COLOR_IS_PACKED - *rowColor++ = packedColor; -#else - *rowColor++ = r; - *rowColor++ = g; - *rowColor++ = b; - *rowColor++ = a; -#endif - -#if DEPTH_IS_PACKED - *rowDepth++ = d; -#else - *rowDepth++ = d0; - *rowDepth++ = d1; - *rowDepth++ = d2; -#endif - } + sw_pixel_t *row = ptr + y*RLSW.framebuffer.width + RLSW.scMin[0]; + for (int x = 0; x < w; x++, row++) *row = value; } } else { + for (int i = 0; i < size; i++, ptr++) *ptr = value; + } +} + +static inline void sw_framebuffer_copy_fast(void* dst) +{ + int size = RLSW.framebuffer.width*RLSW.framebuffer.height; + const sw_pixel_t *pixels = RLSW.framebuffer.pixels; + +#if SW_COLOR_BUFFER_BITS == 8 + uint8_t *dst8 = (uint8_t*)dst; + for (int i = 0; i < size; i++) dst8[i] = pixels[i].color[0]; +#elif SW_COLOR_BUFFER_BITS == 16 + uint16_t *dst16 = (uint16_t*)dst; + for (int i = 0; i < size; i++) dst16[i] = *(uint16_t*)pixels[i].color; +#else // 32 bits + uint32_t *dst32 = (uint32_t*)dst; + #if SW_GL_FRAMEBUFFER_COPY_BGRA for (int i = 0; i < size; i++) { -#if COLOR_IS_PACKED - *pColor++ = packedColor; -#else - *pColor++ = r; - *pColor++ = g; - *pColor++ = b; - *pColor++ = a; -#endif - -#if DEPTH_IS_PACKED - *pDepth++ = d; -#else - *pDepth++ = d0; - *pDepth++ = d1; - *pDepth++ = d2; -#endif + const uint8_t *c = pixels[i].color; + dst32[i] = (uint32_t)c[2] | ((uint32_t)c[1] << 8) | ((uint32_t)c[0] << 16) | ((uint32_t)c[3] << 24); } - } + #else // RGBA + for (int i = 0; i < size; i++) dst32[i] = *(uint32_t*)pixels[i].color; + #endif +#endif } #define DEFINE_FRAMEBUFFER_COPY_BEGIN(name, DST_PTR_T) \ -static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \ +static inline void sw_framebuffer_copy_to_##name(int x, int y, int w, int h, DST_PTR_T *dst) \ { \ - const void *src = RLSW.framebuffer.color; \ + const int stride = RLSW.framebuffer.width; \ + const sw_pixel_t *src = RLSW.framebuffer.pixels + (y*stride + x); \ \ - for (int iy = y; iy < h; iy++) { \ - for (int ix = x; ix < w; ix++) { \ + for (int iy = 0; iy < h; iy++) { \ + const sw_pixel_t *line = src; \ + for (int ix = 0; ix < w; ix++) { \ uint8_t color[4]; \ - sw_framebuffer_read_color8(color, src); \ + sw_framebuffer_read_color8(color, line); \ #define DEFINE_FRAMEBUFFER_COPY_END() \ - INC_COLOR_PTR(src); \ + ++line; \ } \ + src += stride; \ } \ } @@ -1620,22 +1511,24 @@ static inline void sw_framebuffer_blit_to_##name( int xSrc, int ySrc, int wSrc, int hSrc, \ DST_PTR_T *dst) \ { \ - const uint8_t *srcBase = (uint8_t*)RLSW.framebuffer.color; \ - int fbWidth = RLSW.framebuffer.width; \ + const sw_pixel_t *srcBase = RLSW.framebuffer.pixels; \ + const int fbWidth = RLSW.framebuffer.width; \ \ - uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ - uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \ + const uint32_t xScale = ((uint32_t)wSrc << 16)/(uint32_t)wDst; \ + const uint32_t yScale = ((uint32_t)hSrc << 16)/(uint32_t)hDst; \ \ for (int dy = 0; dy < hDst; dy++) { \ uint32_t yFix = ((uint32_t)ySrc << 16) + dy*yScale; \ int sy = yFix >> 16; \ + const sw_pixel_t *srcLine = srcBase + sy*fbWidth + xSrc; \ \ + const sw_pixel_t *srcPtr = srcLine; \ for (int dx = 0; dx < wDst; dx++) { \ uint32_t xFix = dx*xScale; \ int sx = xFix >> 16; \ - const void *srcPtr = GET_COLOR_PTR(srcBase, sy*fbWidth + sx); \ + const sw_pixel_t *pixel = srcPtr + sx; \ uint8_t color[4]; \ - sw_framebuffer_read_color8(color, srcPtr); \ + sw_framebuffer_read_color8(color, pixel); #define DEFINE_FRAMEBUFFER_BLIT_END() \ } \ @@ -2378,8 +2271,7 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, \ /* Pre-calculate the starting pointers for the framebuffer row */ \ int y = (int)start->screen[1]; \ - void *cptr = GET_COLOR_PTR(RLSW.framebuffer.color, y*RLSW.framebuffer.width + xStart); \ - void *dptr = GET_DEPTH_PTR(RLSW.framebuffer.depth, y*RLSW.framebuffer.width + xStart); \ + sw_pixel_t *ptr = RLSW.framebuffer.pixels + y*RLSW.framebuffer.width + xStart; \ \ /* Scanline rasterization */ \ for (int x = xStart; x < xEnd; x++) \ @@ -2395,12 +2287,12 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, if (ENABLE_DEPTH_TEST) \ { \ /* TODO: Implement different depth funcs? */ \ - float depth = sw_framebuffer_read_depth(dptr); \ + float depth = sw_framebuffer_read_depth(ptr); \ if (z > depth) goto discard; \ } \ \ /* TODO: Implement depth mask */ \ - sw_framebuffer_write_depth(dptr, z); \ + sw_framebuffer_write_depth(ptr, z); \ \ if (ENABLE_TEXTURE) \ { \ @@ -2417,13 +2309,13 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ + sw_framebuffer_read_color(dstColor, ptr); \ sw_blend_colors(dstColor, srcColor); \ - sw_framebuffer_write_color(cptr, dstColor); \ + sw_framebuffer_write_color(ptr, dstColor); \ } \ else \ { \ - sw_framebuffer_write_color(cptr, srcColor); \ + sw_framebuffer_write_color(ptr, srcColor); \ } \ \ /* Increment the interpolation parameter, UVs, and pointers */ \ @@ -2439,9 +2331,7 @@ static inline void FUNC_NAME(const sw_texture_t *tex, const sw_vertex_t *start, u += dUdx; \ v += dVdx; \ } \ - \ - INC_COLOR_PTR(cptr); \ - INC_DEPTH_PTR(dptr); \ + ++ptr; \ } \ } @@ -2809,8 +2699,7 @@ static inline void FUNC_NAME(void) const sw_texture_t *tex; \ if (ENABLE_TEXTURE) tex = &RLSW.loadedTextures[RLSW.currentTexture]; \ \ - void *cDstBase = RLSW.framebuffer.color; \ - void *dDstBase = RLSW.framebuffer.depth; \ + sw_pixel_t *pixels = RLSW.framebuffer.pixels; \ int wDst = RLSW.framebuffer.width; \ \ float zScanline = v0->homogeneous[2] + dZdx*xSubstep + dZdy*ySubstep; \ @@ -2826,8 +2715,7 @@ static inline void FUNC_NAME(void) \ for (int y = yMin; y < yMax; y++) \ { \ - void *cptr = GET_COLOR_PTR(cDstBase, y*wDst + xMin); \ - void *dptr = GET_DEPTH_PTR(dDstBase, y*wDst + xMin); \ + sw_pixel_t *ptr = pixels + y*wDst + xMin; \ \ float z = zScanline; \ float u = uScanline; \ @@ -2855,12 +2743,12 @@ static inline void FUNC_NAME(void) if (ENABLE_DEPTH_TEST) \ { \ /* TODO: Implement different depth funcs? */ \ - float depth = sw_framebuffer_read_depth(dptr); \ + float depth = sw_framebuffer_read_depth(ptr); \ if (z > depth) goto discard; \ } \ \ /* TODO: Implement depth mask */ \ - sw_framebuffer_write_depth(dptr, z); \ + sw_framebuffer_write_depth(ptr, z); \ \ if (ENABLE_TEXTURE) \ { \ @@ -2875,11 +2763,11 @@ static inline void FUNC_NAME(void) if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ + sw_framebuffer_read_color(dstColor, ptr); \ sw_blend_colors(dstColor, srcColor); \ - sw_framebuffer_write_color(cptr, dstColor); \ + sw_framebuffer_write_color(ptr, dstColor); \ } \ - else sw_framebuffer_write_color(cptr, srcColor); \ + else sw_framebuffer_write_color(ptr, srcColor); \ \ discard: \ z += dZdx; \ @@ -2887,15 +2775,12 @@ static inline void FUNC_NAME(void) color[1] += dCdx[1]; \ color[2] += dCdx[2]; \ color[3] += dCdx[3]; \ - \ if (ENABLE_TEXTURE) \ { \ u += dUdx; \ v += dVdx; \ } \ - \ - INC_COLOR_PTR(cptr); \ - INC_DEPTH_PTR(dptr); \ + ++ptr; \ } \ \ zScanline += dZdy; \ @@ -3119,8 +3004,7 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ float a = v0->color[3] + aInc*substep; \ \ const int fbWidth = RLSW.framebuffer.width; \ - void *cBuffer = RLSW.framebuffer.color; \ - void *dBuffer = RLSW.framebuffer.depth; \ + sw_pixel_t *pixels = RLSW.framebuffer.pixels; \ \ int numPixels = (int)(steps - substep) + 1; \ \ @@ -3130,28 +3014,26 @@ static inline void FUNC_NAME(const sw_vertex_t *v0, const sw_vertex_t *v1) \ int px = (int)(x - 0.5f); \ int py = (int)(y - 0.5f); \ \ - int offset = py*fbWidth + px; \ - void *dptr = GET_DEPTH_PTR(dBuffer, offset); \ + sw_pixel_t *ptr = pixels + py*fbWidth + px; \ \ if (ENABLE_DEPTH_TEST) \ { \ - float depth = sw_framebuffer_read_depth(dptr); \ + float depth = sw_framebuffer_read_depth(ptr); \ if (z > depth) goto discard; \ } \ \ - sw_framebuffer_write_depth(dptr, z); \ + sw_framebuffer_write_depth(ptr, z); \ \ - void *cptr = GET_COLOR_PTR(cBuffer, offset); \ float color[4] = {r, g, b, a}; \ \ if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ + sw_framebuffer_read_color(dstColor, ptr); \ sw_blend_colors(dstColor, color); \ - sw_framebuffer_write_color(cptr, dstColor); \ + sw_framebuffer_write_color(ptr, dstColor); \ } \ - else sw_framebuffer_write_color(cptr, color); \ + else sw_framebuffer_write_color(ptr, color); \ \ discard: \ x += xInc; y += yInc; z += zInc; \ @@ -3292,27 +3174,24 @@ static inline void FUNC_NAME(int x, int y, float z, const float color[4]) \ } \ \ int offset = y*RLSW.framebuffer.width + x; \ - \ - void *dptr = GET_DEPTH_PTR(RLSW.framebuffer.depth, offset); \ + sw_pixel_t *ptr = RLSW.framebuffer.pixels + offset; \ \ if (ENABLE_DEPTH_TEST) \ { \ - float depth = sw_framebuffer_read_depth(dptr); \ + float depth = sw_framebuffer_read_depth(ptr); \ if (z > depth) return; \ } \ \ - sw_framebuffer_write_depth(dptr, z); \ - \ - void *cptr = GET_COLOR_PTR(RLSW.framebuffer.color, offset); \ + sw_framebuffer_write_depth(ptr, z); \ \ if (ENABLE_COLOR_BLEND) \ { \ float dstColor[4]; \ - sw_framebuffer_read_color(dstColor, cptr); \ + sw_framebuffer_read_color(dstColor, ptr); \ sw_blend_colors(dstColor, color); \ - sw_framebuffer_write_color(cptr, dstColor); \ + sw_framebuffer_write_color(ptr, dstColor); \ } \ - else sw_framebuffer_write_color(cptr, color); \ + else sw_framebuffer_write_color(ptr, color); \ } #define DEFINE_POINT_THICK_RASTER(FUNC_NAME, RASTER_FUNC) \ @@ -3598,11 +3477,9 @@ bool swInit(int w, int h) RLSW.freeTextureIds = (uint32_t *)SW_MALLOC(SW_MAX_TEXTURES*sizeof(uint32_t)); if (RLSW.loadedTextures == NULL) { swClose(); return false; } - RLSW.clearColor[0] = 0.0f; - RLSW.clearColor[1] = 0.0f; - RLSW.clearColor[2] = 0.0f; - RLSW.clearColor[3] = 1.0f; - RLSW.clearDepth = 1.0f; + const float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + sw_framebuffer_write_color(&RLSW.clearValue, clearColor); + sw_framebuffer_write_depth(&RLSW.clearValue, 1.0f); RLSW.currentMatrixMode = SW_MODELVIEW; RLSW.currentMatrix = &RLSW.stackModelview[0]; @@ -3669,8 +3546,7 @@ void swClose(void) } } - SW_FREE(RLSW.framebuffer.color); - SW_FREE(RLSW.framebuffer.depth); + SW_FREE(RLSW.framebuffer.pixels); SW_FREE(RLSW.loadedTextures); SW_FREE(RLSW.freeTextureIds); @@ -3686,17 +3562,8 @@ void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, { sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type); - if (w <= 0) - { - RLSW.errCode = SW_INVALID_VALUE; - return; - } - - if (h <= 0) - { - RLSW.errCode = SW_INVALID_VALUE; - return; - } + if (w <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } + if (h <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } if (w > RLSW.framebuffer.width) w = RLSW.framebuffer.width; if (h > RLSW.framebuffer.height) h = RLSW.framebuffer.height; @@ -3704,6 +3571,25 @@ void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, x = sw_clampi(x, 0, w); y = sw_clampi(y, 0, h); + if (x >= w || y >= h) return; + + if (x == 0 && y == 0 && w == RLSW.framebuffer.width && h == RLSW.framebuffer.height) + { + #if SW_COLOR_BUFFER_BITS == 32 + if (pFormat == SW_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8) + { + sw_framebuffer_copy_fast(pixels); + return; + } + #elif SW_COLOR_BUFFER_BITS == 16 + if (pFormat == SW_PIXELFORMAT_UNCOMPRESSED_R5G6B5) + { + sw_framebuffer_copy_fast(pixels); + return; + } + #endif + } + switch (pFormat) { case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_copy_to_GRAYALPHA(x, y, w, h, (uint8_t *)pixels); break; @@ -3730,17 +3616,13 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr { sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type); - if (wSrc <= 0) + if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc) { - RLSW.errCode = SW_INVALID_VALUE; - return; + swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels); } - if (hSrc <= 0) - { - RLSW.errCode = SW_INVALID_VALUE; - return; - } + if (wSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } + if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } if (wSrc > RLSW.framebuffer.width) wSrc = RLSW.framebuffer.width; if (hSrc > RLSW.framebuffer.height) hSrc = RLSW.framebuffer.height; @@ -3770,14 +3652,6 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr } } -void *swGetColorBuffer(int *w, int *h) -{ - if (w) *w = RLSW.framebuffer.width; - if (h) *h = RLSW.framebuffer.height; - - return RLSW.framebuffer.color; -} - void swEnable(SWstate state) { switch (state) @@ -3821,10 +3695,11 @@ void swGetFloatv(SWget name, float *v) { case SW_COLOR_CLEAR_VALUE: { - v[0] = RLSW.clearColor[0]; - v[1] = RLSW.clearColor[1]; - v[2] = RLSW.clearColor[2]; - v[3] = RLSW.clearColor[3]; + sw_framebuffer_read_color(v, &RLSW.clearValue); + } break; + case SW_DEPTH_CLEAR_VALUE: + { + v[0] = sw_framebuffer_read_depth(&RLSW.clearValue); } break; case SW_CURRENT_COLOR: { @@ -3932,10 +3807,13 @@ void swScissor(int x, int y, int width, int height) void swClearColor(float r, float g, float b, float a) { - RLSW.clearColor[0] = r; - RLSW.clearColor[1] = g; - RLSW.clearColor[2] = b; - RLSW.clearColor[3] = a; + float v[4] = { r, g, b, a }; + sw_framebuffer_write_color(&RLSW.clearValue, v); +} + +void swClearDepth(float depth) +{ + sw_framebuffer_write_depth(&RLSW.clearValue, depth); } void swClear(uint32_t bitmask) @@ -3944,15 +3822,15 @@ void swClear(uint32_t bitmask) if ((bitmask & (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT)) == (SW_COLOR_BUFFER_BIT | SW_DEPTH_BUFFER_BIT)) { - sw_framebuffer_fill(RLSW.framebuffer.color, RLSW.framebuffer.depth,size, RLSW.clearColor, RLSW.clearDepth); + sw_framebuffer_fill(RLSW.framebuffer.pixels, size, RLSW.clearValue); } else if (bitmask & (SW_COLOR_BUFFER_BIT)) { - sw_framebuffer_fill_color(RLSW.framebuffer.color, size, RLSW.clearColor); + sw_framebuffer_fill_color(RLSW.framebuffer.pixels, size, RLSW.clearValue.color); } else if (bitmask & SW_DEPTH_BUFFER_BIT) { - sw_framebuffer_fill_depth(RLSW.framebuffer.depth, size, RLSW.clearDepth); + sw_framebuffer_fill_depth(RLSW.framebuffer.pixels, size, RLSW.clearValue.depth); } } @@ -4525,7 +4403,7 @@ void swDrawArrays(SWdraw mode, int offset, int count) float u, v; if (texcoords) { - int idx = 2 * i; + int idx = 2*i; u = texcoords[idx]; v = texcoords[idx + 1]; } @@ -4536,8 +4414,8 @@ void swDrawArrays(SWdraw mode, int offset, int count) } float texcoord[2]; - texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12]; - texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13]; + texcoord[0] = texMatrix[0]*u + texMatrix[4]*v + texMatrix[12]; + texcoord[1] = texMatrix[1]*u + texMatrix[5]*v + texMatrix[13]; float color[4] = { defaultColor[0], @@ -4548,14 +4426,14 @@ void swDrawArrays(SWdraw mode, int offset, int count) if (colors) { - int idx = 4 * i; + int idx = 4*i; color[0] *= (float)colors[idx]*SW_INV_255; color[1] *= (float)colors[idx + 1]*SW_INV_255; color[2] *= (float)colors[idx + 2]*SW_INV_255; color[3] *= (float)colors[idx + 3]*SW_INV_255; } - int idx = 3 * i; + int idx = 3*i; float position[4] = { positions[idx], positions[idx + 1], @@ -4621,7 +4499,7 @@ void swDrawElements(SWdraw mode, int count, int type, const void *indices) float u, v; if (texcoords) { - int idx = 2 * index; + int idx = 2*index; u = texcoords[idx]; v = texcoords[idx + 1]; } @@ -4632,8 +4510,8 @@ void swDrawElements(SWdraw mode, int count, int type, const void *indices) } float texcoord[2]; - texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12]; - texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13]; + texcoord[0] = texMatrix[0]*u + texMatrix[4]*v + texMatrix[12]; + texcoord[1] = texMatrix[1]*u + texMatrix[5]*v + texMatrix[13]; float color[4] = { defaultColor[0], @@ -4644,14 +4522,14 @@ void swDrawElements(SWdraw mode, int count, int type, const void *indices) if (colors) { - int idx = 4 * index; + int idx = 4*index; color[0] *= (float)colors[idx]*SW_INV_255; color[1] *= (float)colors[idx + 1]*SW_INV_255; color[2] *= (float)colors[idx + 2]*SW_INV_255; color[3] *= (float)colors[idx + 3]*SW_INV_255; } - int idx = 3 * index; + int idx = 3*index; float position[4] = { positions[idx], positions[idx + 1], From 93a21c7e1300c073acc0a9c5b69d8cdfb6127255 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Oct 2025 19:55:28 +0100 Subject: [PATCH 090/102] Support other graphic backends on some platforms --- src/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile b/src/Makefile index 48ff50b30..0895d8f95 100644 --- a/src/Makefile +++ b/src/Makefile @@ -262,16 +262,16 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # On DRM OpenGL ES 2.0 must be used - GRAPHICS = GRAPHICS_API_OPENGL_ES2 + GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 endif ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 - GRAPHICS = GRAPHICS_API_OPENGL_ES2 + GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 #GRAPHICS = GRAPHICS_API_OPENGL_ES3 endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) # By default use OpenGL ES 2.0 on Android - GRAPHICS = GRAPHICS_API_OPENGL_ES2 + GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 endif # Define default C compiler and archiver to pack library: CC, AR From 78870335e6e791055c38c007b28bca9eea37947d Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Oct 2025 19:55:35 +0100 Subject: [PATCH 091/102] Update rlgl.h --- src/rlgl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rlgl.h b/src/rlgl.h index e6a1c9432..99e9037d5 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -21,6 +21,7 @@ * Internal buffer (and resources) must be manually unloaded calling rlglClose() * * CONFIGURATION: +* #define GRAPHICS_API_OPENGL_11_SOFTWARE * #define GRAPHICS_API_OPENGL_11 * #define GRAPHICS_API_OPENGL_21 * #define GRAPHICS_API_OPENGL_33 From f106301d4678a392d67c564666ac77a4d5d1946c Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Oct 2025 20:11:29 +0100 Subject: [PATCH 092/102] ADDED: Some code sample for RISC-V RVV vector instructions -WIP- --- src/external/rlsw.h | 96 ++++++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 31 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index ba2716790..cfb2d236f 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -616,69 +616,74 @@ SWAPI void swBindTexture(uint32_t id); #include // Required for: floorf(), fabsf() #if defined(__FMA__) && defined(__AVX2__) -# define SW_HAS_FMA_AVX2 -# include + #define SW_HAS_FMA_AVX2 + #include #endif #if defined(__FMA__) && defined(__AVX__) -# define SW_HAS_FMA_AVX -# include + #define SW_HAS_FMA_AVX + #include #endif #if defined(__AVX2__) -# define SW_HAS_AVX2 -# include + #define SW_HAS_AVX2 + #include #endif #if defined(__AVX__) -# define SW_HAS_AVX -# include + #define SW_HAS_AVX + #include #endif #if defined(__SSE4_2__) -# define SW_HAS_SSE42 -# include + #define SW_HAS_SSE42 + #include #endif #if defined(__SSE4_1__) -# define SW_HAS_SSE41 -# include + #define SW_HAS_SSE41 + #include #endif #if defined(__SSSE3__) -# define SW_HAS_SSSE3 -# include + #define SW_HAS_SSSE3 + #include #endif #if defined(__SSE3__) -# define SW_HAS_SSE3 -# include + #define SW_HAS_SSE3 + #include #endif #if defined(__SSE2__) -# define SW_HAS_SSE2 -# include + #define SW_HAS_SSE2 + #include #endif #if defined(__SSE__) -# define SW_HAS_SSE -# include + #define SW_HAS_SSE + #include #endif #if defined(__ARM_NEON) || defined(__aarch64__) -# if defined(__ARM_FEATURE_FMA) -# define SW_HAS_NEON_FMA -# else -# define SW_HAS_NEON -# endif -# include + #if defined(__ARM_FEATURE_FMA) + #define SW_HAS_NEON_FMA + #else + #define SW_HAS_NEON + #endif + #include +#endif + +#ifdef __riscv_vector + #define SW_HAS_RVV + #include #endif //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- #define SW_PI 3.14159265358979323846f -#define SW_INV_255 0.00392156862745098f +#define SW_INV_255 0.00392156862745098f // 1.0f/255.0f #define SW_DEG2RAD (SW_PI/180.0f) #define SW_RAD2DEG (180.0f/SW_PI) @@ -1102,6 +1107,27 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) clamped = _mm_packs_epi32(clamped, clamped); // s32 -> s16 (saturated) clamped = _mm_packus_epi16(clamped, clamped); // s16 -> u8 (saturated < 0 to 0) *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); +#elif defined(SW_HAS_RVV) + // TODO: Sample code generated by AI, needs testing and review + size_t vl = vsetvl_e32m1(4); // Load up to 4 floats into a vector register + vfloat32m1_t vsrc = vle32_v_f32m1(src, vl); // Load float32 values + + // Clamp to [0.0f, 1.0f] + vfloat32m1_t vzero = vfmv_v_f_f32m1(0.0f, vl); + vfloat32m1_t vone = vfmv_v_f_f32m1(1.0f, vl); + vsrc = vfmin_vv_f32m1(vsrc, vone, vl); + vsrc = vfmax_vv_f32m1(vsrc, vzero, vl); + + // Multiply by 255.0f and add 0.5f for rounding + vfloat32m1_t vscaled = vfmul_vf_f32m1(vsrc, 255.0f, vl); + vscaled = vfadd_vf_f32m1(vscaled, 0.5f, vl); + + // Convert to unsigned integer (truncate toward zero) + vuint32m1_t vu32 = vfcvt_xu_f_v_u32m1(vscaled, vl); + + // Narrow from u32 -> u8 + vuint8m1_t vu8 = vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero + vse8_v_u8m1(dst, vu8, vl); // Store result #else for (int i = 0; i < 4; i++) { @@ -1123,18 +1149,26 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) floats = vmulq_n_f32(floats, SW_INV_255); vst1q_f32(dst, floats); #elif defined(SW_HAS_SSE41) - __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); + __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t *)src); __m128i ints = _mm_cvtepu8_epi32(bytes); __m128 floats = _mm_cvtepi32_ps(ints); floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255)); _mm_storeu_ps(dst, floats); #elif defined(SW_HAS_SSE2) - __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); + __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t *)src); bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128()); __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128()); __m128 floats = _mm_cvtepi32_ps(ints); floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255)); _mm_storeu_ps(dst, floats); +#elif defined(SW_HAS_RVV) + // TODO: Sample code generated by AI, needs testing and review + size_t vl = vsetvl_e8m1(4); // Set vector length for 8-bit input elements + vuint8m1_t vsrc_u8 = vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers + vuint32m1_t vsrc_u32 = vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers + vfloat32m1_t vsrc_f32 = vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32 + vfloat32m1_t vnorm = vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize + vse32_v_f32m1(dst, vnorm, vl); // Store result #else dst[0] = (float)src[0]*SW_INV_255; dst[1] = (float)src[1]*SW_INV_255; @@ -2672,8 +2706,8 @@ static inline void FUNC_NAME(void) float ySubstep = 1.0f - sw_fract(v0->screen[1]); \ \ /* Calculation of vertex gradients in X and Y */ \ - float dUdx, dVdx; \ - float dUdy, dVdy; \ + float dUdx = 0.0f, dVdx = 0.0f; \ + float dUdy = 0.0f, dVdy = 0.0f; \ if (ENABLE_TEXTURE) { \ dUdx = (v1->texcoord[0] - v0->texcoord[0])*wRcp; \ dVdx = (v1->texcoord[1] - v0->texcoord[1])*wRcp; \ From a844a943b5c89fc7c1bef550bd24cd5109649fa7 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Oct 2025 20:45:21 +0100 Subject: [PATCH 093/102] It seems alignas() is C11 and raylib is C99, so not fully supported #5312 Added a workaround but it has other probably undesired implications --- src/external/rlsw.h | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index cfb2d236f..6f59bba95 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -610,11 +610,19 @@ SWAPI void swBindTexture(uint32_t id); #define RLSW_IMPLEMENTATION #if defined(RLSW_IMPLEMENTATION) -#include #include #include #include // Required for: floorf(), fabsf() +#if defined(_MSC_VER) + #define ALIGNAS(x) __declspec(align(x)) +#elif defined(__GNUC__) || defined(__clang__) + #define ALIGNAS(x) __attribute__((aligned(x))) +#else + #include + #define ALIGNAS(x) alignas(x) +#endif + #if defined(__FMA__) && defined(__AVX2__) #define SW_HAS_FMA_AVX2 #include @@ -687,8 +695,8 @@ SWAPI void swBindTexture(uint32_t id); #define SW_DEG2RAD (SW_PI/180.0f) #define SW_RAD2DEG (180.0f/SW_PI) -#define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS/8) -#define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS/8) +#define SW_COLOR_PIXEL_SIZE 4 //(SW_COLOR_BUFFER_BITS >> 3) +#define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS >> 3) #if (SW_COLOR_BUFFER_BITS == 8) #define SW_COLOR_TYPE uint8_t @@ -817,14 +825,15 @@ typedef struct { float ty; // Texel height } sw_texture_t; -typedef struct { - alignas(SW_COLOR_PIXEL_SIZE) +// Pixel data type +// WARNING: ALIGNAS() macro requires a constant value (not operand) +typedef ALIGNAS(SW_COLOR_PIXEL_SIZE) struct { SW_COLOR_TYPE color[SW_COLOR_PACK_COMP]; SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP]; } sw_pixel_t; typedef struct { - sw_pixel_t* pixels; + sw_pixel_t *pixels; int width; int height; int allocSz; From bf5c00f7e063ee0d236a48a9ba2be799d84c8b4c Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 28 Oct 2025 20:57:31 +0100 Subject: [PATCH 094/102] RE-ADDED: `swGetColorBuffer()` for convenience #5312 `PLATFORM_DRM` depends on it but if there is a better approach to get the buffer, it can just be removed again and replaced by alternative. --- src/external/rlsw.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 6f59bba95..f6c15ee1d 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -531,6 +531,7 @@ SWAPI void swClose(void); SWAPI bool swResizeFramebuffer(int w, int h); SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels); SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels); +SWAPI void *swGetColorBuffer(int *w, int *h); SWAPI void swEnable(SWstate state); SWAPI void swDisable(SWstate state); @@ -3695,6 +3696,14 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr } } +void *swGetColorBuffer(int *w, int *h) +{ + if (w) *w = RLSW.framebuffer.width; + if (h) *h = RLSW.framebuffer.height; + + return (void *)RLSW.framebuffer.pixels->color; +} + void swEnable(SWstate state) { switch (state) From cbff0fa22c9b9eb9662971731c4cee2c6898661a Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Tue, 28 Oct 2025 23:50:04 +0100 Subject: [PATCH 095/102] [rlsw] Fix axis aligned quad detection (#5314) * fix `sw_quad_is_axis_aligned` * align fix * remove swGetColorBuffer and tweak DRM * review alignment --- src/external/rlsw.h | 96 +++++++++++++++++++++++++-------------- src/platforms/rcore_drm.c | 21 +-------- 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index f6c15ee1d..78ff3fa59 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -531,7 +531,6 @@ SWAPI void swClose(void); SWAPI bool swResizeFramebuffer(int w, int h); SWAPI void swCopyFramebuffer(int x, int y, int w, int h, SWformat format, SWtype type, void *pixels); SWAPI void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySrc, int wSrc, int hSrc, SWformat format, SWtype type, void *pixels); -SWAPI void *swGetColorBuffer(int *w, int *h); SWAPI void swEnable(SWstate state); SWAPI void swDisable(SWstate state); @@ -616,12 +615,23 @@ SWAPI void swBindTexture(uint32_t id); #include // Required for: floorf(), fabsf() #if defined(_MSC_VER) - #define ALIGNAS(x) __declspec(align(x)) + #define SW_ALIGN(x) __declspec(align(x)) #elif defined(__GNUC__) || defined(__clang__) - #define ALIGNAS(x) __attribute__((aligned(x))) + #define SW_ALIGN(x) __attribute__((aligned(x))) #else - #include - #define ALIGNAS(x) alignas(x) + #define SW_ALIGN(x) // Do nothing if not available +#endif + +#if defined(_M_X64) || defined(__x86_64__) + #define SW_ARCH_X86_64 +#elif defined(_M_IX86) || defined(__i386__) + #define SW_ARCH_X86 +#elif defined(_M_ARM) || defined(__arm__) + #define SW_ARCH_ARM32 +#elif defined(_M_ARM64) || defined(__aarch64__) + #define SW_ARCH_ARM64 +#elif defined(__riscv) + #define SW_ARCH_RISCV #endif #if defined(__FMA__) && defined(__AVX2__) @@ -696,8 +706,15 @@ SWAPI void swBindTexture(uint32_t id); #define SW_DEG2RAD (SW_PI/180.0f) #define SW_RAD2DEG (180.0f/SW_PI) -#define SW_COLOR_PIXEL_SIZE 4 //(SW_COLOR_BUFFER_BITS >> 3) +#define SW_COLOR_PIXEL_SIZE (SW_COLOR_BUFFER_BITS >> 3) #define SW_DEPTH_PIXEL_SIZE (SW_DEPTH_BUFFER_BITS >> 3) +#define SW_PIXEL_SIZE (SW_COLOR_PIXEL_SIZE + SW_DEPTH_PIXEL_SIZE) + +#if (SW_PIXEL_SIZE <= 4) + #define SW_PIXEL_ALIGNMENT 4 +#else // if (SW_PIXEL_SIZE <= 8) + #define SW_PIXEL_ALIGNMENT 8 +#endif #if (SW_COLOR_BUFFER_BITS == 8) #define SW_COLOR_TYPE uint8_t @@ -827,10 +844,12 @@ typedef struct { } sw_texture_t; // Pixel data type -// WARNING: ALIGNAS() macro requires a constant value (not operand) -typedef ALIGNAS(SW_COLOR_PIXEL_SIZE) struct { +typedef SW_ALIGN(SW_PIXEL_ALIGNMENT) struct { SW_COLOR_TYPE color[SW_COLOR_PACK_COMP]; SW_DEPTH_TYPE depth[SW_DEPTH_PACK_COMP]; +#if (SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT != 0) + uint8_t padding[SW_PIXEL_ALIGNMENT - SW_PIXEL_SIZE % SW_PIXEL_ALIGNMENT]; +#endif } sw_pixel_t; typedef struct { @@ -2624,25 +2643,38 @@ static inline void sw_quad_clip_and_project(void) static inline bool sw_quad_is_axis_aligned(void) { - int horizontal = 0; - int vertical = 0; - + // Reject quads with perspective projection + // The fast path assumes affine (non-perspective) quads, + // so we require all vertices to have homogeneous w = 1.0 for (int i = 0; i < 4; i++) { if (RLSW.vertexBuffer[i].homogeneous[3] != 1.0f) return false; - - const float *v0 = RLSW.vertexBuffer[i].position; - const float *v1 = RLSW.vertexBuffer[(i + 1)%4].position; - - float dx = v1[0] - v0[0]; - float dy = v1[1] - v0[1]; - - if ((fabsf(dx) > 1e-6f) && (fabsf(dy) < 1e-6f)) horizontal++; - else if ((fabsf(dy) > 1e-6f) && (fabsf(dx) < 1e-6f)) vertical++; - else return false; // Diagonal edge -> not axis-aligned } - return ((horizontal == 2) && (vertical == 2)); + // Epsilon tolerance in screen space (pixels) + const float epsilon = 0.5f; + + // Fetch screen-space positions for the four quad vertices + const float *p0 = RLSW.vertexBuffer[0].screen; + const float *p1 = RLSW.vertexBuffer[1].screen; + const float *p2 = RLSW.vertexBuffer[2].screen; + const float *p3 = RLSW.vertexBuffer[3].screen; + + // Compute edge vectors between consecutive vertices + // These define the four sides of the quad in screen space + float dx01 = p1[0] - p0[0], dy01 = p1[1] - p0[1]; + float dx12 = p2[0] - p1[0], dy12 = p2[1] - p1[1]; + float dx23 = p3[0] - p2[0], dy23 = p3[1] - p2[1]; + float dx30 = p0[0] - p3[0], dy30 = p0[1] - p3[1]; + + // Each edge must be either horizontal or vertical within epsilon tolerance + // If any edge deviates significantly from either axis, the quad is not axis-aligned + if (!((fabsf(dy01) < epsilon) || (fabsf(dx01) < epsilon))) return false; + if (!((fabsf(dy12) < epsilon) || (fabsf(dx12) < epsilon))) return false; + if (!((fabsf(dy23) < epsilon) || (fabsf(dx23) < epsilon))) return false; + if (!((fabsf(dy30) < epsilon) || (fabsf(dx30) < epsilon))) return false; + + return true; } static inline void sw_quad_sort_cw(const sw_vertex_t* *output) @@ -3660,11 +3692,6 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr { sw_pixelformat_t pFormat = (sw_pixelformat_t)sw_get_pixel_format(format, type); - if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc) - { - swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels); - } - if (wSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } if (hSrc <= 0) { RLSW.errCode = SW_INVALID_VALUE; return; } @@ -3674,6 +3701,13 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr xSrc = sw_clampi(xSrc, 0, wSrc); ySrc = sw_clampi(ySrc, 0, hSrc); + // Check if the sizes are identical after clamping the source to avoid unexpected issues + // REVIEW: This repeats the operations if true, so we could make a copy function without these checks + if (xDst == xSrc && yDst == ySrc && wDst == wSrc && hDst == hSrc) + { + swCopyFramebuffer(xSrc, ySrc, wSrc, hSrc, format, type, pixels); + } + switch (pFormat) { case SW_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: sw_framebuffer_blit_to_GRAYALPHA(xDst, yDst, wDst, hDst, xSrc, ySrc, wSrc, hSrc, (uint8_t *)pixels); break; @@ -3696,14 +3730,6 @@ void swBlitFramebuffer(int xDst, int yDst, int wDst, int hDst, int xSrc, int ySr } } -void *swGetColorBuffer(int *w, int *h) -{ - if (w) *w = RLSW.framebuffer.width; - if (h) *h = RLSW.framebuffer.height; - - return (void *)RLSW.framebuffer.pixels->color; -} - void swEnable(SWstate state) { switch (state) diff --git a/src/platforms/rcore_drm.c b/src/platforms/rcore_drm.c index a08a76bce..da0d08aca 100644 --- a/src/platforms/rcore_drm.c +++ b/src/platforms/rcore_drm.c @@ -824,15 +824,6 @@ void SwapScreenBuffer(void) return; } - // Get the software rendered color buffer - int bufferWidth = 0, bufferHeight = 0; - void *colorBuffer = swGetColorBuffer(&bufferWidth, &bufferHeight); - if (!colorBuffer) - { - TRACELOG(LOG_ERROR, "DISPLAY: Failed to get software color buffer"); - return; - } - // Retrieving the dimensions of the display mode used drmModeModeInfo *mode = &platform.connector->modes[platform.modeIndex]; uint32_t width = mode->hdisplay; @@ -900,16 +891,8 @@ void SwapScreenBuffer(void) } // Copy the software rendered buffer to the dumb buffer with scaling if needed - if (bufferWidth == width && bufferHeight == height) - { - // Direct copy if sizes match - swCopyFramebuffer(0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer); - } - else - { - // Scale the software buffer to match the display mode - swBlitFramebuffer(0, 0, width, height, 0, 0, bufferWidth, bufferHeight, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer); - } + // NOTE: RLSW will make a simple copy if the dimensions match + swBlitFramebuffer(0, 0, width, height, 0, 0, width, height, SW_RGBA, SW_UNSIGNED_BYTE, dumbBuffer); // Unmap the buffer munmap(dumbBuffer, creq.size); From f16d5ce1ddb0b0a447a30ef02d6a5a76d6fea4e2 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Oct 2025 11:12:04 +0100 Subject: [PATCH 096/102] REVIEWED: Make sure SSE is being used when compiling with MSVC Added log info and some formatting for visibility --- src/external/rlsw.h | 167 ++++++++++++++++++++++++-------------------- 1 file changed, 91 insertions(+), 76 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 78ff3fa59..ab8756e56 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -94,11 +94,9 @@ #ifndef SW_MALLOC #define SW_MALLOC(sz) malloc(sz) #endif - #ifndef SW_REALLOC #define SW_REALLOC(ptr, newSz) realloc(ptr, newSz) #endif - #ifndef SW_FREE #define SW_FREE(ptr) free(ptr) #endif @@ -152,12 +150,6 @@ #define SW_CLIP_EPSILON 1e-4f #endif -#ifdef __cplusplus - #define CURLY_INIT(name) name -#else - #define CURLY_INIT(name) (name) -#endif - //---------------------------------------------------------------------------------- // OpenGL Compatibility Types //---------------------------------------------------------------------------------- @@ -610,9 +602,19 @@ SWAPI void swBindTexture(uint32_t id); #define RLSW_IMPLEMENTATION #if defined(RLSW_IMPLEMENTATION) -#include -#include -#include // Required for: floorf(), fabsf() +#include // Required for: malloc(), free() +#include // Required for: NULL, size_t, uint8_t, uint16_t, uint32_t... +#include // Required for: sinf(), cosf(), floorf(), fabsf(), sqrtf(), roundf() + +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define SW_SUPPORT_LOG_INFO +#if defined(SW_SUPPORT_LOG_INFO) //&& defined(_DEBUG) // WARNING: LOG() output required for this tool + #include + #define SW_LOG(...) printf(__VA_ARGS__) +#else + #define SW_LOG(...) +#endif #if defined(_MSC_VER) #define SW_ALIGN(x) __declspec(align(x)) @@ -634,56 +636,47 @@ SWAPI void swBindTexture(uint32_t id); #define SW_ARCH_RISCV #endif +// Check for SIMD vector instructions #if defined(__FMA__) && defined(__AVX2__) #define SW_HAS_FMA_AVX2 #include #endif - #if defined(__FMA__) && defined(__AVX__) #define SW_HAS_FMA_AVX #include #endif - #if defined(__AVX2__) #define SW_HAS_AVX2 #include #endif - #if defined(__AVX__) #define SW_HAS_AVX #include #endif - #if defined(__SSE4_2__) #define SW_HAS_SSE42 #include #endif - #if defined(__SSE4_1__) #define SW_HAS_SSE41 #include #endif - #if defined(__SSSE3__) #define SW_HAS_SSSE3 #include #endif - #if defined(__SSE3__) #define SW_HAS_SSE3 #include #endif - -#if defined(__SSE2__) +#if defined(__SSE2__) || (defined(_M_AMD64) || defined(_M_X64)) // SSE2 x64 #define SW_HAS_SSE2 #include #endif - #if defined(__SSE__) #define SW_HAS_SSE #include #endif - #if defined(__ARM_NEON) || defined(__aarch64__) #if defined(__ARM_FEATURE_FMA) #define SW_HAS_NEON_FMA @@ -692,12 +685,17 @@ SWAPI void swBindTexture(uint32_t id); #endif #include #endif - -#ifdef __riscv_vector +#if defined(__riscv_vector) #define SW_HAS_RVV #include #endif +#ifdef __cplusplus + #define SW_CURLY_INIT(name) name +#else + #define SW_CURLY_INIT(name) (name) +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -717,68 +715,68 @@ SWAPI void swBindTexture(uint32_t id); #endif #if (SW_COLOR_BUFFER_BITS == 8) - #define SW_COLOR_TYPE uint8_t - #define SW_COLOR_IS_PACKED 1 - #define SW_COLOR_PACK_COMP 1 + #define SW_COLOR_TYPE uint8_t + #define SW_COLOR_IS_PACKED 1 + #define SW_COLOR_PACK_COMP 1 #define SW_PACK_COLOR(r,g,b) ((((uint8_t)((r)*7+0.5f))&0x07)<<5 | (((uint8_t)((g)*7+0.5f))&0x07)<<2 | ((uint8_t)((b)*3+0.5f))&0x03) - #define SW_UNPACK_R(p) (((p)>>5)&0x07) - #define SW_UNPACK_G(p) (((p)>>2)&0x07) - #define SW_UNPACK_B(p) ((p)&0x03) - #define SW_SCALE_R(v) ((v)*255+3)/7 - #define SW_SCALE_G(v) ((v)*255+3)/7 - #define SW_SCALE_B(v) ((v)*255+1)/3 - #define SW_TO_FLOAT_R(v) ((v)*(1.0f/7.0f)) - #define SW_TO_FLOAT_G(v) ((v)*(1.0f/7.0f)) - #define SW_TO_FLOAT_B(v) ((v)*(1.0f/3.0f)) + #define SW_UNPACK_R(p) (((p)>>5)&0x07) + #define SW_UNPACK_G(p) (((p)>>2)&0x07) + #define SW_UNPACK_B(p) ((p)&0x03) + #define SW_SCALE_R(v) ((v)*255+3)/7 + #define SW_SCALE_G(v) ((v)*255+3)/7 + #define SW_SCALE_B(v) ((v)*255+1)/3 + #define SW_TO_FLOAT_R(v) ((v)*(1.0f/7.0f)) + #define SW_TO_FLOAT_G(v) ((v)*(1.0f/7.0f)) + #define SW_TO_FLOAT_B(v) ((v)*(1.0f/3.0f)) #elif (SW_COLOR_BUFFER_BITS == 16) - #define SW_COLOR_TYPE uint16_t - #define SW_COLOR_IS_PACKED 1 - #define SW_COLOR_PACK_COMP 1 + #define SW_COLOR_TYPE uint16_t + #define SW_COLOR_IS_PACKED 1 + #define SW_COLOR_PACK_COMP 1 #define SW_PACK_COLOR(r,g,b) ((((uint16_t)((r)*31+0.5f))&0x1F)<<11 | (((uint16_t)((g)*63+0.5f))&0x3F)<<5 | ((uint16_t)((b)*31+0.5f))&0x1F) - #define SW_UNPACK_R(p) (((p)>>11)&0x1F) - #define SW_UNPACK_G(p) (((p)>>5)&0x3F) - #define SW_UNPACK_B(p) ((p)&0x1F) - #define SW_SCALE_R(v) ((v)*255+15)/31 - #define SW_SCALE_G(v) ((v)*255+31)/63 - #define SW_SCALE_B(v) ((v)*255+15)/31 - #define SW_TO_FLOAT_R(v) ((v)*(1.0f/31.0f)) - #define SW_TO_FLOAT_G(v) ((v)*(1.0f/63.0f)) - #define SW_TO_FLOAT_B(v) ((v)*(1.0f/31.0f)) + #define SW_UNPACK_R(p) (((p)>>11)&0x1F) + #define SW_UNPACK_G(p) (((p)>>5)&0x3F) + #define SW_UNPACK_B(p) ((p)&0x1F) + #define SW_SCALE_R(v) ((v)*255+15)/31 + #define SW_SCALE_G(v) ((v)*255+31)/63 + #define SW_SCALE_B(v) ((v)*255+15)/31 + #define SW_TO_FLOAT_R(v) ((v)*(1.0f/31.0f)) + #define SW_TO_FLOAT_G(v) ((v)*(1.0f/63.0f)) + #define SW_TO_FLOAT_B(v) ((v)*(1.0f/31.0f)) #else // 32 bits - #define SW_COLOR_TYPE uint8_t - #define SW_COLOR_IS_PACKED 0 - #define SW_COLOR_PACK_COMP 4 + #define SW_COLOR_TYPE uint8_t + #define SW_COLOR_IS_PACKED 0 + #define SW_COLOR_PACK_COMP 4 #endif #if (SW_DEPTH_BUFFER_BITS == 8) - #define SW_DEPTH_TYPE uint8_t - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX UINT8_MAX - #define SW_DEPTH_SCALE (1.0f/UINT8_MAX) - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) - #define SW_UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT8_MAX + #define SW_DEPTH_SCALE (1.0f/UINT8_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) #elif (SW_DEPTH_BUFFER_BITS == 16) - #define SW_DEPTH_TYPE uint16_t - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX UINT16_MAX - #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) - #define SW_UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE uint16_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT16_MAX + #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) #else // 24 bits - #define SW_DEPTH_TYPE uint8_t - #define SW_DEPTH_IS_PACKED 0 - #define SW_DEPTH_PACK_COMP 3 - #define SW_DEPTH_MAX 0xFFFFFF - #define SW_DEPTH_SCALE (1.0f/0xFFFFFF) - #define SW_PACK_DEPTH_0(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFF) - #define SW_PACK_DEPTH_1(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFF) - #define SW_PACK_DEPTH_2(d) ((uint32_t)((d)*SW_DEPTH_MAX)&0xFF) - #define SW_UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 0 + #define SW_DEPTH_PACK_COMP 3 + #define SW_DEPTH_MAX 0xFFFFFF + #define SW_DEPTH_SCALE (1.0f/0xFFFFFF) + #define SW_PACK_DEPTH_0(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFF) + #define SW_PACK_DEPTH_1(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFF) + #define SW_PACK_DEPTH_2(d) ((uint32_t)((d)*SW_DEPTH_MAX)&0xFF) + #define SW_UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) #endif -#define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) +#define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) #define SW_STATE_CHECK_EX(state, flags) (((state) & (flags)) == (flags)) #define SW_STATE_SCISSOR_TEST (1 << 0) @@ -3607,6 +3605,23 @@ bool swInit(int w, int h) RLSW.loadedTextures[0].ty = 0.5f; RLSW.loadedTextureCount = 1; + + SW_LOG("INFO: RLSW: Software renderer initialized successfully\n"); +#if defined(SW_HAS_FMA_AVX) && defined(SW_HAS_FMA_AVX2) + SW_LOG("INFO: RLSW: Using SIMD instructions: FMA AVX\n"); +#endif +#if defined(SW_HAS_AVX) || defined(SW_HAS_AVX2) + SW_LOG("INFO: RLSW: Using SIMD instructions: AVX\n"); +#endif +#if defined(SW_HAS_SSE) || defined(SW_HAS_SSE2) || defined(SW_HAS_SSE3) || defined(SW_HAS_SSE41) || defined(SW_HAS_SSE42) + SW_LOG("INFO: RLSW: Using SIMD instructions: SSE\n"); +#endif +#if defined(SW_HAS_NEON_FMA) || defined(SW_HAS_NEON) + SW_LOG("INFO: RLSW: Using SIMD instructions: NEON\n"); +#endif +#if defined(SW_HAS_RVV) + SW_LOG("INFO: RLSW: Using SIMD instructions: RVV\n"); +#endif return true; } @@ -3626,7 +3641,7 @@ void swClose(void) SW_FREE(RLSW.loadedTextures); SW_FREE(RLSW.freeTextureIds); - RLSW = CURLY_INIT(sw_context_t) { 0 }; + RLSW = SW_CURLY_INIT(sw_context_t) { 0 }; } bool swResizeFramebuffer(int w, int h) From 3389c80f498307a7546d868f7a9fcf18d23c65ae Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Oct 2025 11:33:08 +0100 Subject: [PATCH 097/102] Update rlsw.h --- src/external/rlsw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index ab8756e56..f102c3efd 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -3613,7 +3613,7 @@ bool swInit(int w, int h) #if defined(SW_HAS_AVX) || defined(SW_HAS_AVX2) SW_LOG("INFO: RLSW: Using SIMD instructions: AVX\n"); #endif -#if defined(SW_HAS_SSE) || defined(SW_HAS_SSE2) || defined(SW_HAS_SSE3) || defined(SW_HAS_SSE41) || defined(SW_HAS_SSE42) +#if defined(SW_HAS_SSE) || defined(SW_HAS_SSE2) || defined(SW_HAS_SSE3) || defined(SW_HAS_SSSE3) || defined(SW_HAS_SSE41) || defined(SW_HAS_SSE42) SW_LOG("INFO: RLSW: Using SIMD instructions: SSE\n"); #endif #if defined(SW_HAS_NEON_FMA) || defined(SW_HAS_NEON) From 127cc1c79ee93f957907f7824eee75ac00dde095 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 29 Oct 2025 22:45:37 +0100 Subject: [PATCH 098/102] REVIEWED: Makefile to support software renderer --- examples/Makefile | 14 +++++++++++++- src/Makefile | 13 +++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index c8500b665..b5e968079 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -486,7 +486,19 @@ endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) # Libraries for DRM compiling # NOTE: Required packages: libasound2-dev (ALSA) - LDLIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lgbm -ldrm -ldl -latomic + LDLIBS = -lraylib -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl -latomic + # TODO: Examples compilation does not define GRAPHICS, is it required? + #ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_ES2) + # LDLIBS += -lGLESv2 -lEGL + #endif +endif +ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) + # Libraries for Windows desktop compilation + LDFLAGS += -L..\src + LDLIBS = -lraylib -lgdi32 -lwinmm -lshcore + ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE) + LDLIBS += -lopengl32 + endif endif ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # Libraries for web (HTML5) compiling diff --git a/src/Makefile b/src/Makefile index 0895d8f95..41867da1c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -228,7 +228,6 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) ifeq ($(ANDROID_ARCH),x86_64) ANDROID_COMPILER_ARCH = x86_64 endif - endif # Define raylib graphics api depending on selected platform @@ -261,8 +260,8 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) #GRAPHICS = GRAPHICS_API_OPENGL_ES2 # Uncomment to use OpenGL ES 2.0 (ANGLE) endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) - # On DRM OpenGL ES 2.0 must be used GRAPHICS ?= GRAPHICS_API_OPENGL_ES2 + #GRAPHICS = GRAPHICS_API_OPENGL_11_SOFTWARE # Uncomment to use software rendering endif ifeq ($(TARGET_PLATFORM),$(filter $(TARGET_PLATFORM),PLATFORM_WEB PLATFORM_WEB_RGFW)) # On HTML5 OpenGL ES 2.0 is used, emscripten translates it to WebGL 1.0 @@ -636,13 +635,19 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW) endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) - LDLIBS = -lGLESv2 -lEGL -ldrm -lgbm -lpthread -lrt -lm -ldl + LDLIBS = -ldrm -lgbm -lpthread -lrt -lm -ldl + ifeq ($(GRAPHICS),GRAPHICS_API_OPENGL_ES2) + LDLIBS += -lGLESv2 -lEGL + endif ifeq ($(RAYLIB_MODULE_AUDIO),TRUE) LDLIBS += -latomic endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_WIN32) - LDLIBS = -lgdi32 -lwinmm -lopengl32 -lshcore + LDLIBS = -lgdi32 -lwinmm -lshcore + ifneq ($(GRAPHICS),GRAPHICS_API_OPENGL_11_SOFTWARE) + LDLIBS += -lopengl32 + endif endif ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID) LDLIBS = -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lc -lm From b2d455400c3946461943902e2b071eaf49407111 Mon Sep 17 00:00:00 2001 From: Dave Goehrig Date: Thu, 30 Oct 2025 19:15:14 +0100 Subject: [PATCH 099/102] Adding SwiftForth language binding (#5319) --- BINDINGS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BINDINGS.md b/BINDINGS.md index 7770f41c2..f2ffaea9e 100644 --- a/BINDINGS.md +++ b/BINDINGS.md @@ -31,6 +31,7 @@ Some people ported raylib to other languages in the form of bindings or wrappers | [rayex](https://github.com/shiryel/rayex) | 3.7 | [elixir](https://elixir-lang.org) | Apache-2.0 | | [raylib-factor](https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor) | 4.5 | [Factor](https://factorcode.org) | BSD | | [raylib-freebasic](https://github.com/WIITD/raylib-freebasic) | **5.0** | [FreeBASIC](https://www.freebasic.net) | MIT | +| [raylib.f](https://github.com/cthulhuology/raylib.f) | **5.5** | [Forth](https://forth.com) | Zlib | | [fortran-raylib](https://github.com/interkosmos/fortran-raylib) | **5.5** | [Fortran](https://fortran-lang.org) | ISC | | [raylib-go](https://github.com/gen2brain/raylib-go) | **5.5** | [Go](https://golang.org) | Zlib | | [raylib-guile](https://github.com/petelliott/raylib-guile) | **auto** | [Guile](https://www.gnu.org/software/guile) | Zlib | From bca54047f9bb735e9fbc3173674a9c1e6503a708 Mon Sep 17 00:00:00 2001 From: Le Juez Victor <90587919+Bigfoot71@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:17:18 +0100 Subject: [PATCH 100/102] [rlsw] Review depth formats and fix depth writing (#5317) * review depth format/writing * adding a note --- src/external/rlsw.h | 58 +++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index f102c3efd..9c510e945 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -114,11 +114,11 @@ #endif #ifndef SW_COLOR_BUFFER_BITS - #define SW_COLOR_BUFFER_BITS 32 //< 32 (rgba), 16 (rgb packed) or 8 (rgb packed) + #define SW_COLOR_BUFFER_BITS 32 //< 32 (rgba), 16 (rgb packed) or 8 (rgb packed) #endif #ifndef SW_DEPTH_BUFFER_BITS - #define SW_DEPTH_BUFFER_BITS 16 //< 24, 16 or 8 + #define SW_DEPTH_BUFFER_BITS 16 //< 32, 24 or 16 #endif #ifndef SW_MAX_PROJECTION_STACK_SIZE @@ -748,32 +748,32 @@ SWAPI void swBindTexture(uint32_t id); #define SW_COLOR_PACK_COMP 4 #endif -#if (SW_DEPTH_BUFFER_BITS == 8) - #define SW_DEPTH_TYPE uint8_t - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX UINT8_MAX - #define SW_DEPTH_SCALE (1.0f/UINT8_MAX) - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) - #define SW_UNPACK_DEPTH(p) (p) -#elif (SW_DEPTH_BUFFER_BITS == 16) - #define SW_DEPTH_TYPE uint16_t - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX UINT16_MAX - #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) - #define SW_UNPACK_DEPTH(p) (p) -#else // 24 bits - #define SW_DEPTH_TYPE uint8_t - #define SW_DEPTH_IS_PACKED 0 - #define SW_DEPTH_PACK_COMP 3 - #define SW_DEPTH_MAX 0xFFFFFF - #define SW_DEPTH_SCALE (1.0f/0xFFFFFF) - #define SW_PACK_DEPTH_0(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFF) - #define SW_PACK_DEPTH_1(d) (((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFF) - #define SW_PACK_DEPTH_2(d) ((uint32_t)((d)*SW_DEPTH_MAX)&0xFF) - #define SW_UNPACK_DEPTH(p) (((p)[0]<<16)|((p)[1]<<8)|(p)[2]) +#if (SW_DEPTH_BUFFER_BITS == 16) + #define SW_DEPTH_TYPE uint16_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT16_MAX + #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) +#elif (SW_DEPTH_BUFFER_BITS == 24) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 0 + #define SW_DEPTH_PACK_COMP 3 + #define SW_DEPTH_MAX 0xFFFFFFU + #define SW_DEPTH_SCALE (1.0f/0xFFFFFFU) + #define SW_PACK_DEPTH_0(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFFU)) + #define SW_PACK_DEPTH_1(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFFU)) + #define SW_PACK_DEPTH_2(d) ((uint8_t)((uint32_t)((d)*SW_DEPTH_MAX)&0xFFU)) + #define SW_UNPACK_DEPTH(p) ((((uint32_t)(p)[0]<<16)|((uint32_t)(p)[1]<<8)|(uint32_t)(p)[2])) +#else // 32 bits + #define SW_DEPTH_TYPE float + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX 1.0f + #define SW_DEPTH_SCALE 1.0f + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)(d)) + #define SW_UNPACK_DEPTH(p) (p) #endif #define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) @@ -1346,6 +1346,8 @@ static inline void sw_framebuffer_write_color(sw_pixel_t *dst, const float src[4 static inline void sw_framebuffer_write_depth(sw_pixel_t *dst, float depth) { + depth = sw_saturate(depth); // REVIEW: An overflow can occur in certain circumstances with clipping, and needs to be reviewed... + #if SW_DEPTH_IS_PACKED dst->depth[0] = SW_PACK_DEPTH(depth); #else From dfc94f64d1e1db5231a68e8ea968378df16f2292 Mon Sep 17 00:00:00 2001 From: Arrangemonk <34814431+Arrangemonk@users.noreply.github.com> Date: Fri, 31 Oct 2025 20:43:27 +0100 Subject: [PATCH 101/102] =?UTF-8?q?Revert=20"UpdateModelAnimation=20does?= =?UTF-8?q?=20matrixtranspose(matrixinvert)=20only=20once=20per=E2=80=A6"?= =?UTF-8?q?=20(#5322)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit e3a562ab57a9fa4a9dbaa3d5ffb67f31c25a4a36. --- src/rmodels.c | 79 ++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/src/rmodels.c b/src/rmodels.c index 3c904c396..ed86fb19a 100644 --- a/src/rmodels.c +++ b/src/rmodels.c @@ -2352,8 +2352,6 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) Mesh mesh = model.meshes[m]; Vector3 animVertex = { 0 }; Vector3 animNormal = { 0 }; - Matrix boneMatrix = { 0 }; - Matrix InverseBoneMatrix = { 0 }; int boneId = 0; int boneCounter = 0; float boneWeight = 0.0; @@ -2361,50 +2359,47 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame) const int vValues = mesh.vertexCount*3; // Skip if missing bone data, causes segfault without on some models - if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue; + if ((mesh.boneWeights == NULL) || (mesh.boneIds == NULL)) continue; - // Iterates over 4 bones per vertex - for (int j = 0; j < 4; j++, boneCounter++) - { - boneWeight = mesh.boneWeights[boneCounter]; - boneId = mesh.boneIds[boneCounter]; + for (int vCounter = 0; vCounter < vValues; vCounter += 3) + { + mesh.animVertices[vCounter] = 0; + mesh.animVertices[vCounter + 1] = 0; + mesh.animVertices[vCounter + 2] = 0; + if (mesh.animNormals != NULL) + { + mesh.animNormals[vCounter] = 0; + mesh.animNormals[vCounter + 1] = 0; + mesh.animNormals[vCounter + 2] = 0; + } - // Early stop when no transformation will be applied - if (boneWeight == 0.0f) continue; + // Iterates over 4 bones per vertex + for (int j = 0; j < 4; j++, boneCounter++) + { + boneWeight = mesh.boneWeights[boneCounter]; + boneId = mesh.boneIds[boneCounter]; - boneMatrix = model.meshes[m].boneMatrices[boneId]; - InverseBoneMatrix = MatrixTranspose(MatrixInvert(boneMatrix)); + // Early stop when no transformation will be applied + if (boneWeight == 0.0f) continue; + animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; + animVertex = Vector3Transform(animVertex,model.meshes[m].boneMatrices[boneId]); + mesh.animVertices[vCounter] += animVertex.x*boneWeight; + mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; + mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; + updated = true; - for (int vCounter = 0; vCounter < vValues; vCounter += 3) - { - mesh.animVertices[vCounter] = 0; - mesh.animVertices[vCounter + 1] = 0; - mesh.animVertices[vCounter + 2] = 0; - if (mesh.animNormals != NULL) - { - mesh.animNormals[vCounter] = 0; - mesh.animNormals[vCounter + 1] = 0; - mesh.animNormals[vCounter + 2] = 0; - } - animVertex = (Vector3){ mesh.vertices[vCounter], mesh.vertices[vCounter + 1], mesh.vertices[vCounter + 2] }; - animVertex = Vector3Transform(animVertex, boneMatrix); - mesh.animVertices[vCounter] += animVertex.x*boneWeight; - mesh.animVertices[vCounter+1] += animVertex.y*boneWeight; - mesh.animVertices[vCounter+2] += animVertex.z*boneWeight; - updated = true; - - // Normals processing - // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) - if ((mesh.normals != NULL) && (mesh.animNormals != NULL)) - { - animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; - animNormal = Vector3Transform(animNormal, InverseBoneMatrix); - mesh.animNormals[vCounter] += animNormal.x*boneWeight; - mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; - mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; - } - } - } + // Normals processing + // NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals) + if ((mesh.normals != NULL) && (mesh.animNormals != NULL )) + { + animNormal = (Vector3){ mesh.normals[vCounter], mesh.normals[vCounter + 1], mesh.normals[vCounter + 2] }; + animNormal = Vector3Transform(animNormal, MatrixTranspose(MatrixInvert(model.meshes[m].boneMatrices[boneId]))); + mesh.animNormals[vCounter] += animNormal.x*boneWeight; + mesh.animNormals[vCounter + 1] += animNormal.y*boneWeight; + mesh.animNormals[vCounter + 2] += animNormal.z*boneWeight; + } + } + } if (updated) { From 02466212100344b00bb3c9d438d2236144070aac Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 1 Nov 2025 21:06:18 +0100 Subject: [PATCH 102/102] REVIEWED: SIMD intrinsics checks and usage --- src/external/rlsw.h | 192 +++++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 92 deletions(-) diff --git a/src/external/rlsw.h b/src/external/rlsw.h index 9c510e945..15ab89d4e 100644 --- a/src/external/rlsw.h +++ b/src/external/rlsw.h @@ -40,6 +40,14 @@ * If not defined, the library is in header only mode and can be included in other headers * or source files without problems. But only ONE file should hold the implementation * +* #define RLSW_USE_SIMD_INTRINSICS +* Detect and use SIMD intrinsics on the host compilation platform +* SIMD could improve rendering considerable vectorizing some raster operations +* but the target platforms running the compiled program with SIMD enabled +* must support the SIMD the program has been built for, making them only +* recommended under specific situations and only if the developers know +* what are they doing; this flag is not defined by default +* * rlsw capabilities could be customized just defining some internal * values before library inclusion (default values listed): * @@ -636,59 +644,58 @@ SWAPI void swBindTexture(uint32_t id); #define SW_ARCH_RISCV #endif -// Check for SIMD vector instructions -#if defined(__FMA__) && defined(__AVX2__) - #define SW_HAS_FMA_AVX2 - #include -#endif -#if defined(__FMA__) && defined(__AVX__) - #define SW_HAS_FMA_AVX - #include -#endif -#if defined(__AVX2__) - #define SW_HAS_AVX2 - #include -#endif -#if defined(__AVX__) - #define SW_HAS_AVX - #include -#endif -#if defined(__SSE4_2__) - #define SW_HAS_SSE42 - #include -#endif -#if defined(__SSE4_1__) - #define SW_HAS_SSE41 - #include -#endif -#if defined(__SSSE3__) - #define SW_HAS_SSSE3 - #include -#endif -#if defined(__SSE3__) - #define SW_HAS_SSE3 - #include -#endif -#if defined(__SSE2__) || (defined(_M_AMD64) || defined(_M_X64)) // SSE2 x64 - #define SW_HAS_SSE2 - #include -#endif -#if defined(__SSE__) - #define SW_HAS_SSE - #include -#endif -#if defined(__ARM_NEON) || defined(__aarch64__) - #if defined(__ARM_FEATURE_FMA) - #define SW_HAS_NEON_FMA - #else - #define SW_HAS_NEON +#if defined(RLSW_USE_SIMD_INTRINSICS) + // Check for SIMD vector instructions + // NOTE: Compiler is responsible to enable required flags for host device, + // supported features are detected at compiler init but varies depending on compiler + // TODO: This logic must be reviewed to avoid the inclusion of multiple headers + // and enable the higher level of SIMD available + #if defined(__FMA__) && defined(__AVX2__) + #define SW_HAS_FMA_AVX2 + #include + #elif defined(__FMA__) && defined(__AVX__) + #define SW_HAS_FMA_AVX + #include + #elif defined(__AVX2__) + #define SW_HAS_AVX2 + #include + #elif defined(__AVX__) + #define SW_HAS_AVX + #include #endif - #include -#endif -#if defined(__riscv_vector) - #define SW_HAS_RVV - #include -#endif + #if defined(__SSE4_2__) + #define SW_HAS_SSE42 + #include + #elif defined(__SSE4_1__) + #define SW_HAS_SSE41 + #include + #elif defined(__SSSE3__) + #define SW_HAS_SSSE3 + #include + #elif defined(__SSE3__) + #define SW_HAS_SSE3 + #include + #elif defined(__SSE2__) || (defined(_M_AMD64) || defined(_M_X64)) // SSE2 x64 + #define SW_HAS_SSE2 + #include + #elif defined(__SSE__) + #define SW_HAS_SSE + #include + #endif + #if defined(__ARM_NEON) || defined(__aarch64__) + #if defined(__ARM_FEATURE_FMA) + #define SW_HAS_NEON_FMA + #else + #define SW_HAS_NEON + #endif + #include + #endif + #if defined(__riscv_vector) + // NOTE: Requires compilation flags: -march=rv64gcv -mabi=lp64d + #define SW_HAS_RVV + #include + #endif +#endif // RLSW_USE_SIMD_INTRINSICS #ifdef __cplusplus #define SW_CURLY_INIT(name) name @@ -749,31 +756,31 @@ SWAPI void swBindTexture(uint32_t id); #endif #if (SW_DEPTH_BUFFER_BITS == 16) - #define SW_DEPTH_TYPE uint16_t - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX UINT16_MAX - #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) - #define SW_UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE uint16_t + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX UINT16_MAX + #define SW_DEPTH_SCALE (1.0f/UINT16_MAX) + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)((d)*SW_DEPTH_MAX)) + #define SW_UNPACK_DEPTH(p) (p) #elif (SW_DEPTH_BUFFER_BITS == 24) - #define SW_DEPTH_TYPE uint8_t - #define SW_DEPTH_IS_PACKED 0 - #define SW_DEPTH_PACK_COMP 3 - #define SW_DEPTH_MAX 0xFFFFFFU - #define SW_DEPTH_SCALE (1.0f/0xFFFFFFU) - #define SW_PACK_DEPTH_0(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFFU)) - #define SW_PACK_DEPTH_1(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFFU)) - #define SW_PACK_DEPTH_2(d) ((uint8_t)((uint32_t)((d)*SW_DEPTH_MAX)&0xFFU)) - #define SW_UNPACK_DEPTH(p) ((((uint32_t)(p)[0]<<16)|((uint32_t)(p)[1]<<8)|(uint32_t)(p)[2])) + #define SW_DEPTH_TYPE uint8_t + #define SW_DEPTH_IS_PACKED 0 + #define SW_DEPTH_PACK_COMP 3 + #define SW_DEPTH_MAX 0xFFFFFFU + #define SW_DEPTH_SCALE (1.0f/0xFFFFFFU) + #define SW_PACK_DEPTH_0(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>16)&0xFFU)) + #define SW_PACK_DEPTH_1(d) ((uint8_t)(((uint32_t)((d)*SW_DEPTH_MAX)>>8)&0xFFU)) + #define SW_PACK_DEPTH_2(d) ((uint8_t)((uint32_t)((d)*SW_DEPTH_MAX)&0xFFU)) + #define SW_UNPACK_DEPTH(p) ((((uint32_t)(p)[0]<<16)|((uint32_t)(p)[1]<<8)|(uint32_t)(p)[2])) #else // 32 bits - #define SW_DEPTH_TYPE float - #define SW_DEPTH_IS_PACKED 1 - #define SW_DEPTH_PACK_COMP 1 - #define SW_DEPTH_MAX 1.0f - #define SW_DEPTH_SCALE 1.0f - #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)(d)) - #define SW_UNPACK_DEPTH(p) (p) + #define SW_DEPTH_TYPE float + #define SW_DEPTH_IS_PACKED 1 + #define SW_DEPTH_PACK_COMP 1 + #define SW_DEPTH_MAX 1.0f + #define SW_DEPTH_SCALE 1.0f + #define SW_PACK_DEPTH(d) ((SW_DEPTH_TYPE)(d)) + #define SW_UNPACK_DEPTH(p) (p) #endif #define SW_STATE_CHECK(flags) (SW_STATE_CHECK_EX(RLSW.stateFlags, (flags))) @@ -1136,25 +1143,26 @@ static inline void sw_float_to_unorm8_simd(uint8_t dst[4], const float src[4]) *(uint32_t*)dst = _mm_cvtsi128_si32(clamped); #elif defined(SW_HAS_RVV) // TODO: Sample code generated by AI, needs testing and review - size_t vl = vsetvl_e32m1(4); // Load up to 4 floats into a vector register - vfloat32m1_t vsrc = vle32_v_f32m1(src, vl); // Load float32 values + // NOTE: RVV 1.0 specs define the use of __riscv_ prefix for instrinsic functions + size_t vl = __riscv_vsetvl_e32m1(4); // Load up to 4 floats into a vector register + vfloat32m1_t vsrc = __riscv_vle32_v_f32m1(src, vl); // Load float32 values // Clamp to [0.0f, 1.0f] - vfloat32m1_t vzero = vfmv_v_f_f32m1(0.0f, vl); - vfloat32m1_t vone = vfmv_v_f_f32m1(1.0f, vl); - vsrc = vfmin_vv_f32m1(vsrc, vone, vl); - vsrc = vfmax_vv_f32m1(vsrc, vzero, vl); + vfloat32m1_t vzero = __riscv_vfmv_v_f_f32m1(0.0f, vl); + vfloat32m1_t vone = __riscv_vfmv_v_f_f32m1(1.0f, vl); + vsrc = __riscv_vfmin_vv_f32m1(vsrc, vone, vl); + vsrc = __riscv_vfmax_vv_f32m1(vsrc, vzero, vl); // Multiply by 255.0f and add 0.5f for rounding - vfloat32m1_t vscaled = vfmul_vf_f32m1(vsrc, 255.0f, vl); - vscaled = vfadd_vf_f32m1(vscaled, 0.5f, vl); + vfloat32m1_t vscaled = __riscv_vfmul_vf_f32m1(vsrc, 255.0f, vl); + vscaled = __riscv_vfadd_vf_f32m1(vscaled, 0.5f, vl); // Convert to unsigned integer (truncate toward zero) - vuint32m1_t vu32 = vfcvt_xu_f_v_u32m1(vscaled, vl); + vuint32m1_t vu32 = __riscv_vfcvt_xu_f_v_u32m1(vscaled, vl); // Narrow from u32 -> u8 - vuint8m1_t vu8 = vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero - vse8_v_u8m1(dst, vu8, vl); // Store result + vuint8m1_t vu8 = __riscv_vnclipu_wx_u8m1(vu32, 0, vl); // Round toward zero + __riscv_vse8_v_u8m1(dst, vu8, vl); // Store result #else for (int i = 0; i < 4; i++) { @@ -1190,12 +1198,12 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4]) _mm_storeu_ps(dst, floats); #elif defined(SW_HAS_RVV) // TODO: Sample code generated by AI, needs testing and review - size_t vl = vsetvl_e8m1(4); // Set vector length for 8-bit input elements - vuint8m1_t vsrc_u8 = vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers - vuint32m1_t vsrc_u32 = vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers - vfloat32m1_t vsrc_f32 = vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32 - vfloat32m1_t vnorm = vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize - vse32_v_f32m1(dst, vnorm, vl); // Store result + size_t vl = __riscv_vsetvl_e8m1(4); // Set vector length for 8-bit input elements + vuint8m1_t vsrc_u8 = __riscv_vle8_v_u8m1(src, vl); // Load 4 unsigned 8-bit integers + vuint32m1_t vsrc_u32 = __riscv_vwcvt_xu_u_v_u32m1(vsrc_u8, vl); // Widen to 32-bit unsigned integers + vfloat32m1_t vsrc_f32 = __riscv_vfcvt_f_xu_v_f32m1(vsrc_u32, vl); // Convert to float32 + vfloat32m1_t vnorm = __riscv_vfmul_vf_f32m1(vsrc_f32, SW_INV_255, vl); // Multiply by 1/255.0 to normalize + __riscv_vse32_v_f32m1(dst, vnorm, vl); // Store result #else dst[0] = (float)src[0]*SW_INV_255; dst[1] = (float)src[1]*SW_INV_255;

    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Ⓢ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 z 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⋘*B=&K#XK(i2y{ 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 z⁣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\`OMCpVD*Y_5Mo`n+@t_yJ^iJpziP1dVnk5w{ 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 S>t_ZA1_n=8KbLh*2~7YVNBA88 literal 0 HcmV?d00001 diff --git a/examples/shaders/resources/mandrill.png b/examples/shaders/resources/mandrill.png new file mode 100644 index 0000000000000000000000000000000000000000..02d058eb0d0d055c85c42f08ae2dfb34709642c9 GIT binary patch literal 197452 zcmeAS@N?(olHy`uVBq!ia0y~yU{nBM4kiW$hS?7-uQM<*FnGE+hE&W^`JFyFm9y%3 zyX^b(JD=Yx-s}IqHtpxDb>Gr%^)MSqY-SM4*5LA<*b|}Y;pv?vxpCnGZbO!dN0_>g zGCk-!I79Btmh!7tpRP7qt+n_3o_oI^|Gn7#Q=ne_{AcF>m*@X~k^leQ^7HpAp1)Z0 zsi3yDFf*yhNcY1Q9j*I6zWwp9|5UiP_DncE_qcH4?QKFQBlgCv)w*)%jYxvm^Y-ZI^Je#IKI^h8 zCC${lS#sA=zDc2LNesI~z@Nwd`vY{+lk)UzZB!!fE}nb$=){eOPM+MmyS#n5TJ&AH zW}~%1$wiqN z>g>&(Kf9-|PiEP<^|PyrNOeK_-ivR_t1r#}_t`%Cq|l?qKMOv*|NqWDE%+tF$pD2t zySLh!S=ksG@2%Yv{?cTB<mA0T8Z-gzu&%R z=&Pt^0HtF=}D2@H*VZK`SNME zc+BmpihJ8~tJBKZ)IZ#vE4%aRzAYQ})P2`W*?DEc|4T=^m#xa)WMpq1t{YxcSNFWY ze)8EOi+=~%_s@)k7ytiH`d3YL+8Y#lh1bZT#@)(jj*Fx{`;dzAk(in3DXs&}ilj z`x~#noDDE|^7zl~+w2>jpID@M#Fk}Q_ExW@Dy_-~ckb*A5c&79zkZiR_0LPMu7)k1 z?A0E%*2~}tx5?qwnB>H|W19|MzT;P>@wK4#?uH3}eul5PzdYMk{`Av6Z3mteSF4hq zXB4Kreeu9V;fO;=Q0Vl;Kk_vn9zN|}&rr7G?zGtRfme&xhMi2Cd{^zrkIpJ(`~3zt zUz!Dq+`4`H{a3d2`+j*@OwlRHo>;IWP-yz}X}YntmUfjdzn1Sv`0?T2ug~J)^+xz)jmEM+F8yoRCZ&#EDI3omVM4xW^odR#58?&sI`{&|IVjR#J=K5svr=XfDQ z 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