Merge branch 'master' into remove_platform_rpi

This commit is contained in:
Ray 2023-09-07 17:40:33 +02:00 committed by GitHub
commit c6ff28c7f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 5478 additions and 384 deletions

View File

@ -24,6 +24,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | Apache-2.0 | https://github.com/shiryel/rayex |
| raylib-factor | 4.0 | [Factor](https://factorcode.org/) | BSD | https://github.com/factor/factor/blob/master/extra/raylib/raylib.factor |
| raylib-freebasic | **4.5** | [FreeBASIC](https://www.freebasic.net/) | MIT | https://github.com/WIITD/raylib-freebasic |
| fortran-raylib | **4.5** | [Fortran](https://fortran-lang.org/) | ISC | https://github.com/interkosmos/fortran-raylib |
| raylib for Pascal | **4.5** | [Object Pascal](https://en.wikipedia.org/wiki/Object_Pascal) | Modified Zlib | https://github.com/tinyBigGAMES/raylib |
| raylib-go | 4.5 | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |

View File

@ -38,14 +38,15 @@ cmake_dependent_option(SUPPORT_MODULE_RAUDIO "Include module: raudio" ON CUSTOMI
cmake_dependent_option(SUPPORT_CAMERA_SYSTEM "Provide camera module (rcamera.h) with multiple predefined cameras: free, 1st/3rd person, orbital" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_GESTURES_SYSTEM "Gestures module is included (rgestures.h) to support gestures detection: tap, hold, swipe, drag" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_MOUSE_GESTURES "Mouse gestures are directly mapped like touches and processed by gestures system" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_SSH_KEYBOARD_RPI "Reconfigure standard input to receive key inputs, works with SSH connection" OFF CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_SSH_KEYBOARD_RPI "Reconfigure standard input to receive key inputs, works with SSH connection" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_DEFAULT_FONT "Default font is loaded on window initialization to be available for the user to render simple text. If enabled, uses external module functions to load default raylib font (module: text)" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_SCREEN_CAPTURE "Allow automatic screen capture of current screen pressing F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_GIF_RECORDING "Allow automatic gif recording of current screen pressing CTRL+F12, defined in KeyCallback()" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_BUSY_WAIT_LOOP "Use busy wait loop for timing sync instead of a high-resolution timer" OFF CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_EVENTS_WAITING "Wait for events passively (sleeping while no events) instead of polling them actively every frame" OFF CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_WINMM_HIGHRES_TIMER "Setting a higher resolution can improve the accuracy of time-out intervals in wait functions" OFF CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_WINMM_HIGHRES_TIMER "Setting a higher resolution can improve the accuracy of time-out intervals in wait functions" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_COMPRESSION_API "Support for compression API" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_EVENTS_AUTOMATION "Support automatic generated events, loading and recording of those events when required" OFF CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_CUSTOM_FRAME_CONTROL "Enabling this flag allows manual control of the frame processes, use at your own risk" OFF CUSTOMIZE_BUILD OFF)
# rshapes.c
@ -58,17 +59,19 @@ cmake_dependent_option(SUPPORT_IMAGE_MANIPULATION "Support multiple image editin
cmake_dependent_option(SUPPORT_FILEFORMAT_PNG "Support loading PNG as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_DDS "Support loading DDS as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_HDR "Support loading HDR as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_PNM "Support loading PNM as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_KTX "Support loading KTX as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_ASTC "Support loading ASTC as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_PIC "Support loading PIC as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_PNM "Support loading PNM as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_KTX "Support loading KTX as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_ASTC "Support loading ASTC as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_BMP "Support loading BMP as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_TGA "Support loading TGA as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_JPG "Support loading JPG as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_GIF "Support loading GIF as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_QOI "Support loading QOI as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_GIF "Support loading GIF as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_QOI "Support loading QOI as textures" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_PSD "Support loading PSD as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_PKM "Support loading PKM as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_PVR "Support loading PVR as textures" ${OFF} CUSTOMIZE_BUILD OFF)
cmake_dependent_option(SUPPORT_FILEFORMAT_SVG "Support loading SVG as textures" ${OFF} CUSTOMIZE_BUILD OFF)
# rtext.c
cmake_dependent_option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON CUSTOMIZE_BUILD ON)
@ -83,6 +86,7 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_MTL "Support loading MTL file format"
cmake_dependent_option(SUPPORT_FILEFORMAT_IQM "Support loading IQM file format" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_GLTF "Support loading GLTF file format" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_VOX "Support loading VOX file format" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_M3D "Support loading M3D file format" ON CUSTOMIZE_BUILD ON)
# raudio.c
cmake_dependent_option(SUPPORT_FILEFORMAT_WAV "Support loading WAV for sound" ON CUSTOMIZE_BUILD ON)
@ -90,6 +94,7 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_OGG "Support loading OGG for sound" O
cmake_dependent_option(SUPPORT_FILEFORMAT_XM "Support loading XM for sound" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_MOD "Support loading MOD for sound" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_MP3 "Support loading MP3 for sound" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_QOA "Support loading QOA for sound" ON CUSTOMIZE_BUILD ON)
cmake_dependent_option(SUPPORT_FILEFORMAT_FLAC "Support loading FLAC for sound" ${OFF} CUSTOMIZE_BUILD OFF)
# utils.c

View File

@ -2,7 +2,7 @@
**raylib is a simple and easy-to-use library to enjoy videogames programming.**
raylib is highly inspired by Borland BGI graphics lib and by XNA framework and it's specially well suited for prototyping, tooling, graphical applications, embedded systems and education.
raylib is highly inspired by Borland BGI graphics lib and by XNA framework and it's especially well suited for prototyping, tooling, graphical applications, embedded systems and education.
*NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming; no fancy interface, no visual helpers, no debug button... just coding in the most pure spartan-programmers way.*

View File

@ -28,6 +28,7 @@ if (${CUSTOMIZE_BUILD})
define_if("raylib" SUPPORT_EVENTS_WAITING)
define_if("raylib" SUPPORT_WINMM_HIGHRES_TIMER)
define_if("raylib" SUPPORT_COMPRESSION_API)
define_if("raylib" SUPPORT_EVENTS_AUTOMATION)
define_if("raylib" SUPPORT_CUSTOM_FRAME_CONTROL)
define_if("raylib" SUPPORT_QUADS_DRAW_MODE)
define_if("raylib" SUPPORT_IMAGE_EXPORT)
@ -36,6 +37,7 @@ if (${CUSTOMIZE_BUILD})
define_if("raylib" SUPPORT_FILEFORMAT_PNG)
define_if("raylib" SUPPORT_FILEFORMAT_DDS)
define_if("raylib" SUPPORT_FILEFORMAT_HDR)
define_if("raylib" SUPPORT_FILEFORMAT_PIC)
define_if("raylib" SUPPORT_FILEFORMAT_PNM)
define_if("raylib" SUPPORT_FILEFORMAT_KTX)
define_if("raylib" SUPPORT_FILEFORMAT_ASTC)
@ -47,6 +49,7 @@ if (${CUSTOMIZE_BUILD})
define_if("raylib" SUPPORT_FILEFORMAT_PSD)
define_if("raylib" SUPPORT_FILEFORMAT_PKM)
define_if("raylib" SUPPORT_FILEFORMAT_PVR)
define_if("raylib" SUPPORT_FILEFORMAT_SVG)
define_if("raylib" SUPPORT_FILEFORMAT_FNT)
define_if("raylib" SUPPORT_FILEFORMAT_TTF)
define_if("raylib" SUPPORT_TEXT_MANIPULATION)
@ -56,11 +59,13 @@ if (${CUSTOMIZE_BUILD})
define_if("raylib" SUPPORT_FILEFORMAT_IQM)
define_if("raylib" SUPPORT_FILEFORMAT_GLTF)
define_if("raylib" SUPPORT_FILEFORMAT_VOX)
define_if("raylib" SUPPORT_FILEFORMAT_M3D)
define_if("raylib" SUPPORT_FILEFORMAT_WAV)
define_if("raylib" SUPPORT_FILEFORMAT_OGG)
define_if("raylib" SUPPORT_FILEFORMAT_XM)
define_if("raylib" SUPPORT_FILEFORMAT_MOD)
define_if("raylib" SUPPORT_FILEFORMAT_MP3)
define_if("raylib" SUPPORT_FILEFORMAT_QOA)
define_if("raylib" SUPPORT_FILEFORMAT_FLAC)
define_if("raylib" SUPPORT_STANDARD_FILEIO)
define_if("raylib" SUPPORT_TRACELOG)

View File

@ -9,8 +9,7 @@ install(
# PKG_CONFIG_LIBS_PRIVATE is used in raylib.pc.in
if (NOT BUILD_SHARED_LIBS)
include(LibraryPathToLinkerFlags)
library_path_to_linker_flags(__PKG_CONFIG_LIBS_PRIVATE "${LIBS_PRIVATE}")
set(PKG_CONFIG_LIBS_PRIVATE ${__PKG_CONFIG_LIBS_PRIVATE} ${GLFW_PKG_LIBS})
set(PKG_CONFIG_LIBS_PRIVATE ${GLFW_PKG_LIBS})
string(REPLACE ";" " " PKG_CONFIG_LIBS_PRIVATE "${PKG_CONFIG_LIBS_PRIVATE}")
elseif (BUILD_SHARED_LIBS)
set(PKG_CONFIG_LIBS_EXTRA "")

View File

@ -228,6 +228,11 @@ ifeq ($(PLATFORM),PLATFORM_DRM)
INCLUDE_PATHS += -I/usr/include/libdrm
endif
# Include GLFW required for examples/others/rlgl_standalone.c
ifeq ($(USE_EXTERNAL_GLFW),FALSE)
all others: INCLUDE_PATHS += -I$(RAYLIB_PATH)/src/external/glfw/include
endif
# Define library paths containing required libs: LDFLAGS
#------------------------------------------------------------------------------------------------
LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
@ -426,7 +431,8 @@ TEXTURES = \
textures/textures_draw_tiled \
textures/textures_polygon \
textures/textures_gif_player \
textures/textures_fog_of_war
textures/textures_fog_of_war \
textures/textures_svg_loading
TEXT = \
text/text_raylib_fonts \
@ -480,6 +486,7 @@ SHADERS = \
shaders/shaders_simple_mask \
shaders/shaders_spotlight \
shaders/shaders_hot_reloading \
shaders/shaders_lightmap \
shaders/shaders_mesh_instancing \
shaders/shaders_multi_sample2d \
shaders/shaders_write_depth \

View File

@ -406,7 +406,8 @@ TEXTURES = \
textures/textures_draw_tiled \
textures/textures_polygon \
textures/textures_gif_player \
textures/textures_fog_of_war
textures/textures_fog_of_war \
textures/textures_svg_loading
TEXT = \
text/text_raylib_fonts \
@ -460,6 +461,7 @@ SHADERS = \
shaders/shaders_simple_mask \
shaders/shaders_spotlight \
shaders/shaders_hot_reloading \
shaders/shaders_lightmap \
shaders/shaders_mesh_instancing \
shaders/shaders_multi_sample2d \
shaders/shaders_write_depth \

View File

@ -79,6 +79,7 @@ int main(void)
{
StopMusicStream(music);
PlayMusicStream(music);
pause = false;
}
// Pause/Resume music playing
@ -134,6 +135,14 @@ int main(void)
DrawRectangle(20, screenHeight - 20 - 12, (int)timePlayed, 12, MAROON);
DrawRectangleLines(20, screenHeight - 20 - 12, screenWidth - 40, 12, GRAY);
// Draw help instructions
DrawRectangle(20, 20, 425, 145, WHITE);
DrawRectangleLines(20, 20, 425, 145, GRAY);
DrawText("PRESS SPACE TO RESTART MUSIC", 40, 40, 20, BLACK);
DrawText("PRESS P TO PAUSE/RESUME", 40, 70, 20, BLACK);
DrawText("PRESS UP/DOWN TO CHANGE SPEED", 40, 100, 20, BLACK);
DrawText(TextFormat("SPEED: %f", pitch), 40, 130, 20, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -63,8 +63,8 @@ int main(void)
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_THIRD_PERSON);
// Select current animation
if (IsKeyPressed(KEY_UP)) animIndex = (animIndex + 1)%animsCount;
else if (IsKeyPressed(KEY_DOWN)) animIndex = (animIndex + animsCount - 1)%animsCount;
if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)) animIndex = (animIndex + 1)%animsCount;
else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) animIndex = (animIndex + animsCount - 1)%animsCount;
// Update model animation
ModelAnimation anim = modelAnimations[animIndex];
@ -85,7 +85,7 @@ int main(void)
EndMode3D();
DrawText("Use the UP/DOWN arrow keys to switch animation", 10, 10, 20, GRAY);
DrawText("Use the LEFT/RIGHT mouse buttons to switch animation", 10, 10, 20, GRAY);
DrawText(TextFormat("Animation: %s", anim.name), 10, GetScreenHeight() - 20, 10, DARKGRAY);
EndDrawing();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -79,8 +79,8 @@ int main(void)
animPlaying = true;
}
// Select animation by pressing A
if (IsKeyPressed(KEY_A))
// Select animation by pressing C
if (IsKeyPressed(KEY_C))
{
animFrameCounter = 0;
animId++;
@ -92,7 +92,7 @@ int main(void)
}
// Toggle skeleton drawing
if (IsKeyPressed(KEY_S)) drawSkeleton ^= 1;
if (IsKeyPressed(KEY_B)) drawSkeleton ^= 1;
// Toggle mesh drawing
if (IsKeyPressed(KEY_M)) drawMesh ^= 1;
@ -149,9 +149,10 @@ int main(void)
EndMode3D();
DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, GetScreenHeight() - 60, 10, MAROON);
DrawText("PRESS A to CYCLE THROUGH ANIMATIONS", 10, GetScreenHeight() - 40, 10, DARKGRAY);
DrawText("PRESS M to toggle MESH, S to toggle SKELETON DRAWING", 10, GetScreenHeight() - 20, 10, DARKGRAY);
DrawText("PRESS SPACE to PLAY MODEL ANIMATION", 10, GetScreenHeight() - 80, 10, MAROON);
DrawText("PRESS N to STEP ONE ANIMATION FRAME", 10, GetScreenHeight() - 60, 10, DARKGRAY);
DrawText("PRESS C to CYCLE THROUGH ANIMATIONS", 10, GetScreenHeight() - 40, 10, DARKGRAY);
DrawText("PRESS M to toggle MESH, B to toggle SKELETON DRAWING", 10, GetScreenHeight() - 20, 10, DARKGRAY);
DrawText("(c) CesiumMan model by KhronosGroup", GetScreenWidth() - 210, GetScreenHeight() - 20, 10, GRAY);
EndDrawing();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -108,7 +108,7 @@ int main(void)
InitWindow(screenWidth, screenHeight, "raylib [easings] example - easings testbed");
Vector2 ballPosition = { 100.0f, 200.0f };
Vector2 ballPosition = { 100.0f, 100.0f };
float t = 0.0f; // Current time (in any unit measure, but same unit as duration)
float d = 300.0f; // Total time it should take to complete (duration)
@ -180,8 +180,8 @@ int main(void)
// Movement computation
if (!paused && ((boundedT && t < d) || !boundedT))
{
ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 100.0f, d);
ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 100.0f, d);
ballPosition.x = Easings[easingX].func(t, 100.0f, 700.0f - 170.0f, d);
ballPosition.y = Easings[easingY].func(t, 100.0f, 400.0f - 170.0f, d);
t += 1.0f;
}
//----------------------------------------------------------------------------------
@ -193,15 +193,15 @@ int main(void)
ClearBackground(RAYWHITE);
// Draw information text
DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 0, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 0, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 0, FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
DrawText(TextFormat("Easing x: %s", Easings[easingX].name), 20, FONT_SIZE, FONT_SIZE, LIGHTGRAY);
DrawText(TextFormat("Easing y: %s", Easings[easingY].name), 20, FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
DrawText(TextFormat("t (%c) = %.2f d = %.2f", (boundedT == true)? 'b' : 'u', t, d), 20, FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
// Draw instructions text
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 0, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
DrawText("Use D and W or A and S keys to change duration", 0, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 0, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
DrawText("Use UP or DOWN keys to choose easing for the y axis", 0, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
DrawText("Use ENTER to play or pause movement, use SPACE to restart", 20, GetScreenHeight() - FONT_SIZE*2, FONT_SIZE, LIGHTGRAY);
DrawText("Use Q and W or A and S keys to change duration", 20, GetScreenHeight() - FONT_SIZE*3, FONT_SIZE, LIGHTGRAY);
DrawText("Use LEFT or RIGHT keys to choose easing for the x axis", 20, GetScreenHeight() - FONT_SIZE*4, FONT_SIZE, LIGHTGRAY);
DrawText("Use UP or DOWN keys to choose easing for the y axis", 20, GetScreenHeight() - FONT_SIZE*5, FONT_SIZE, LIGHTGRAY);
// Draw ball
DrawCircleV(ballPosition, 16.0f, MAROON);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -10,7 +10,7 @@ varying vec4 fragColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
uniform float secondes;
uniform float seconds;
uniform vec2 size;
@ -29,8 +29,8 @@ void main() {
float boxTop = 0.0;
vec2 p = fragTexCoord;
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth;
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight;
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (seconds * speedX)) * ampX * pixelWidth;
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (seconds * speedY)) * ampY * pixelHeight;
gl_FragColor = texture2D(texture0, p)*colDiffuse*fragColor;
}

View File

@ -11,7 +11,7 @@ uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
uniform float secondes;
uniform float seconds;
uniform vec2 size;
@ -30,8 +30,8 @@ void main() {
float boxTop = 0.0;
vec2 p = fragTexCoord;
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (secondes * speedX)) * ampX * pixelWidth;
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (secondes * speedY)) * ampY * pixelHeight;
p.x += cos((fragTexCoord.y - boxTop) * freqX / ( pixelWidth * 750.0) + (seconds * speedX)) * ampX * pixelWidth;
p.y += sin((fragTexCoord.x - boxLeft) * freqY * aspect / ( pixelHeight * 750.0) + (seconds * speedY)) * ampY * pixelHeight;
finalColor = texture(texture0, p)*colDiffuse*fragColor;
}

View File

@ -81,7 +81,7 @@ int main(void)
EndShaderMode();
DrawText("Shader-based\ntexture\noutline", 10, 10, 20, GRAY);
DrawText("Scroll mouse wheel to\nchange outline size", 10, 72, 20, GRAY);
DrawText(TextFormat("Outline size: %i px", (int)outlineSize), 10, 120, 20, MAROON);
DrawFPS(710, 10);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 258 KiB

View File

@ -46,7 +46,7 @@ int main(void)
// Load shader and setup location points and values
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/wave.fs", GLSL_VERSION));
int secondsLoc = GetShaderLocation(shader, "secondes");
int secondsLoc = GetShaderLocation(shader, "seconds");
int freqXLoc = GetShaderLocation(shader, "freqX");
int freqYLoc = GetShaderLocation(shader, "freqY");
int ampXLoc = GetShaderLocation(shader, "ampX");

View File

@ -99,6 +99,9 @@ int main(void)
DrawText(TextFormat("Collision Area: %i", (int)boxCollision.width*(int)boxCollision.height), GetScreenWidth()/2 - 100, screenUpperLimit + 10, 20, BLACK);
}
// Draw help instructions
DrawText("Press SPACE to PAUSE/RESUME", 20, screenHeight - 35, 20, LIGHTGRAY);
DrawFPS(10, 10);
EndDrawing();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -52,6 +52,8 @@ int main(void)
// Set bilinear scale filter for better font scaling
SetTextureFilter(font.texture, TEXTURE_FILTER_BILINEAR);
SetTextLineSpacing(54); // Set line spacing for multiline text (when line breaks are included '\n')
// Free codepoints, atlas has already been generated
free(codepointsNoDups);

View File

@ -47,6 +47,8 @@ int main(void)
// NOTE: We define a font base size of 32 pixels tall and up-to 250 characters
Font fontTtf = LoadFontEx("resources/pixantiqua.ttf", 32, 0, 250);
SetTextLineSpacing(48); // Set line spacing for multiline text (when line breaks are included '\n')
bool useTtf = false;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second

View File

@ -187,12 +187,11 @@ int main(void)
// Add a new set of emojis when SPACE is pressed
if (IsKeyPressed(KEY_SPACE)) RandomizeEmoji();
// Set the selected emoji and copy its text to clipboard
// Set the selected emoji
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hovered != -1) && (hovered != selected))
{
selected = hovered;
selectedPos = hoveredPos;
SetClipboardText(messages[emoji[selected].message].text);
}
Vector2 mouse = GetMousePosition();
@ -342,7 +341,7 @@ static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec,
{
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
float textOffsetY = 0; // Offset between lines (on line break '\n')
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw
float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -134,7 +134,8 @@ int main(void)
(Vector2){ 0, 0 }, 0.0f, WHITE);
// Draw player current tile
DrawText(TextFormat("Current tile: [%i,%i]", playerTileX, playerTileY), 10, 10, 20, LIME);
DrawText(TextFormat("Current tile: [%i,%i]", playerTileX, playerTileY), 10, 10, 20, RAYWHITE);
DrawText("ARROW KEYS to move", 10, screenHeight-25, 20, RAYWHITE);
EndDrawing();
//----------------------------------------------------------------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -64,6 +64,8 @@ int main(void)
DrawTexture(textures[currentTexture], screenWidth/2 - textures[currentTexture].width/2, screenHeight/2 - textures[currentTexture].height/2, WHITE);
DrawText("Press LEFT MOUSE BUTTON to rotate the image clockwise", 250, 420, 10, DARKGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,72 @@
/*******************************************************************************************
*
* raylib [textures] example - SVG loading and texture creation
*
* NOTE: Images are loaded in CPU memory (RAM); textures are loaded in GPU memory (VRAM)
*
* Example originally created with raylib 4.2, last time updated with raylib 4.2
*
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software
*
* Copyright (c) 2022 Dennis Meinen (@bixxy#4258 on Discord)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [textures] example - svg loading");
// NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
Image image = LoadImageSvg("resources/test.svg", 400, 350); // Loaded in CPU memory (RAM)
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM)
UnloadImage(image); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//---------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE);
//Red border to illustrate how the SVG is centered within the specified dimensions
DrawRectangleLines((screenWidth / 2 - texture.width / 2) - 1, (screenHeight / 2 - texture.height / 2) - 1, texture.width + 2, texture.height + 2, RED);
DrawText("this IS a texture loaded from an SVG file!", 300, 410, 10, GRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Texture unloading
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -776,7 +776,7 @@ clean: clean_shell_$(PLATFORM_SHELL)
@echo "removed all generated files!"
clean_shell_sh:
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so*
rm -fv *.o $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).a $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).bc $(RAYLIB_RELEASE_PATH)/lib$(RAYLIB_LIB_NAME).so* raygui.c physac.c
ifeq ($(PLATFORM),PLATFORM_ANDROID)
rm -fv $(NATIVE_APP_GLUE)/android_native_app_glue.o
endif
@ -788,4 +788,6 @@ clean_shell_cmd:
cd $(RAYLIB_RELEASE_PATH) & \
del lib$(RAYLIB_LIB_NAME).a /s & \
del lib$(RAYLIB_LIB_NAME)dll.a /s & \
del $(RAYLIB_LIB_NAME).dll /s
del $(RAYLIB_LIB_NAME).dll /s & \
del raygui.c /s & \
del physac.c /s

View File

@ -22,15 +22,38 @@ pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.built
}
raylib.addCSourceFiles(&.{
srcdir ++ "/raudio.c",
srcdir ++ "/rcore.c",
srcdir ++ "/rmodels.c",
srcdir ++ "/rshapes.c",
srcdir ++ "/rtext.c",
srcdir ++ "/rtextures.c",
srcdir ++ "/utils.c",
}, raylib_flags);
if (options.raudio) {
raylib.addCSourceFiles(&.{
srcdir ++ "/raudio.c",
}, raylib_flags);
}
if (options.rmodels) {
raylib.addCSourceFiles(&.{
srcdir ++ "/rmodels.c",
}, &[_][]const u8{
"-fno-sanitize=undefined", // https://github.com/raysan5/raylib/issues/1891
} ++ raylib_flags);
}
if (options.rshapes) {
raylib.addCSourceFiles(&.{
srcdir ++ "/rshapes.c",
}, raylib_flags);
}
if (options.rtext) {
raylib.addCSourceFiles(&.{
srcdir ++ "/rtext.c",
}, raylib_flags);
}
if (options.rtextures) {
raylib.addCSourceFiles(&.{
srcdir ++ "/rtextures.c",
}, raylib_flags);
}
var gen_step = std.build.Step.WriteFile.create(b);
raylib.step.dependOn(&gen_step.step);
@ -137,6 +160,11 @@ pub fn addRaylib(b: *std.Build, target: std.zig.CrossTarget, optimize: std.built
}
pub const Options = struct {
raudio: bool = true,
rmodels: bool = true,
rshapes: bool = true,
rtext: bool = true,
rtextures: bool = true,
raygui: bool = false,
platform_drm: bool = false,
};
@ -152,19 +180,24 @@ pub fn build(b: *std.Build) void {
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const raygui = b.option(bool, "raygui", "Compile with raygui support");
const platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)");
const defaults = Options{};
const options = Options{
.platform_drm = b.option(bool, "platform_drm", "Compile raylib in native mode (no X11)") orelse defaults.platform_drm,
.raudio = b.option(bool, "raudio", "Compile with audio support") orelse defaults.raudio,
.rmodels = b.option(bool, "rmodels", "Compile with models support") orelse defaults.rmodels,
.rtext = b.option(bool, "rtext", "Compile with text support") orelse defaults.rtext,
.rtextures = b.option(bool, "rtextures", "Compile with textures support") orelse defaults.rtextures,
.rshapes = b.option(bool, "rshapes", "Compile with shapes support") orelse defaults.rshapes,
.raygui = b.option(bool, "raygui", "Compile with raygui support") orelse defaults.raygui,
};
const lib = addRaylib(b, target, optimize, .{
.raygui = raygui orelse false,
.platform_drm = platform_drm orelse false,
});
const lib = addRaylib(b, target, optimize, options);
lib.installHeader("src/raylib.h", "raylib.h");
lib.installHeader("src/raymath.h", "raymath.h");
lib.installHeader("src/rlgl.h", "rlgl.h");
if (raygui orelse false) {
if (options.raygui) {
lib.installHeader("../raygui/src/raygui.h", "raygui.h");
}

View File

@ -141,7 +141,7 @@
//------------------------------------------------------------------------------------
// Module: rtextures - Configuration Flags
//------------------------------------------------------------------------------------
// Select the desired fileformats to be supported for image data loading
// Selecte desired fileformats to be supported for image data loading
#define SUPPORT_FILEFORMAT_PNG 1
//#define SUPPORT_FILEFORMAT_BMP 1
//#define SUPPORT_FILEFORMAT_TGA 1
@ -150,13 +150,13 @@
#define SUPPORT_FILEFORMAT_QOI 1
//#define SUPPORT_FILEFORMAT_PSD 1
#define SUPPORT_FILEFORMAT_DDS 1
#define SUPPORT_FILEFORMAT_HDR 1
//#define SUPPORT_FILEFORMAT_HDR 1
//#define SUPPORT_FILEFORMAT_PIC 1
//#define SUPPORT_FILEFORMAT_PNM 1
//#define SUPPORT_FILEFORMAT_KTX 1
//#define SUPPORT_FILEFORMAT_ASTC 1
//#define SUPPORT_FILEFORMAT_PKM 1
//#define SUPPORT_FILEFORMAT_PVR 1
//#define SUPPORT_FILEFORMAT_SVG 1
// Support image export functionality (.png, .bmp, .tga, .jpg, .qoi)
#define SUPPORT_IMAGE_EXPORT 1

3053
src/external/nanosvg.h vendored Normal file

File diff suppressed because it is too large Load Diff

1458
src/external/nanosvgrast.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -227,17 +227,20 @@ typedef struct tagBITMAPINFOHEADER {
#define QOA_MALLOC RL_MALLOC
#define QOA_FREE RL_FREE
#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
#if defined(_MSC_VER) // Disable some MSVC warning
#pragma warning(push)
#pragma warning(disable : 4018)
#pragma warning(disable : 4267)
#pragma warning(disable : 4244)
#endif
#define QOA_IMPLEMENTATION
#include "external/qoa.h" // QOA loading and saving functions
#include "external/qoaplay.c" // QOA stream playing helper functions
#if defined(_MSC_VER)
#pragma warning(pop) // Disable MSVC warning suppression
#endif
#endif
#if defined(SUPPORT_FILEFORMAT_FLAC)
@ -254,7 +257,7 @@ typedef struct tagBITMAPINFOHEADER {
#define JARXM_MALLOC RL_MALLOC
#define JARXM_FREE RL_FREE
#if defined(_MSC_VER ) // jar_xm has warnings on windows, so disable them just for this file
#if defined(_MSC_VER) // Disable some MSVC warning
#pragma warning(push)
#pragma warning(disable : 4244)
#endif
@ -263,7 +266,7 @@ typedef struct tagBITMAPINFOHEADER {
#include "external/jar_xm.h" // XM loading functions
#if defined(_MSC_VER)
#pragma warning( pop )
#pragma warning(pop) // Disable MSVC warning suppression
#endif
#endif
@ -410,8 +413,8 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write)
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
#endif
@ -729,11 +732,11 @@ Wave LoadWave(const char *fileName)
Wave wave = { 0 };
// Loading file to memory
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
// Loading wave from memory data
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, fileSize);
if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, dataSize);
RL_FREE(fileData);
@ -2616,10 +2619,10 @@ static const char *GetFileExtension(const char *fileName)
}
// Load data from file into a buffer
static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
static unsigned char *LoadFileData(const char *fileName, int *dataSize)
{
unsigned char *data = NULL;
*bytesRead = 0;
*dataSize = 0;
if (fileName != NULL)
{
@ -2639,7 +2642,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
*bytesRead = count;
*dataSize = count;
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
@ -2656,7 +2659,7 @@ static unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead
}
// Save data to file from buffer
static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
static bool SaveFileData(const char *fileName, void *data, int dataSize)
{
if (fileName != NULL)
{
@ -2664,10 +2667,10 @@ static bool SaveFileData(const char *fileName, void *data, unsigned int bytesToW
if (file != NULL)
{
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
fclose(file);

View File

@ -1075,10 +1075,10 @@ RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
// Files management functions
RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read)
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success
RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success
@ -1115,6 +1115,7 @@ RLAPI unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize
// Input-related functions: keyboard
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again (Only PLATFORM_DESKTOP)
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
@ -1192,6 +1193,8 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out
RLAPI void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); // Draw line using quadratic bezier curves with a control point
RLAPI void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color); // Draw line using cubic bezier curves with 2 control points
RLAPI void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color); // Draw a B-Spline line, minimum 4 points
RLAPI void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color); // Draw a Catmull Rom spline line, minimum 4 points
RLAPI void DrawLineStrip(Vector2 *points, int pointCount, Color color); // Draw lines sequence
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
@ -1242,6 +1245,7 @@ RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2);
// NOTE: These functions do not require GPU access
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
RLAPI Image LoadImageSvg(const char *fileNameOrString, int width, int height); // Load image from SVG file data or string with specified size
RLAPI Image LoadImageAnim(const char *fileName, int *frames); // Load image sequence from file (frames appended to image.data)
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
@ -1368,13 +1372,13 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters, use NULL for fontChars and 0 for glyphCount to load the default character set
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI bool IsFontReady(Font font); // Check if a font is ready
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **recs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
RLAPI void UnloadFont(Font font); // Unload font from GPU memory (VRAM)
RLAPI bool ExportFontAsCode(Font font, const char *fileName); // Export font as code file, returns true on success
@ -1384,7 +1388,7 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
// Text font info functions
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
@ -1503,10 +1507,10 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
// Model animations loading/unloading functions
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount); // Load model animations from file
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount); // Load model animations from file
RLAPI void UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data
RLAPI void UnloadModelAnimations(ModelAnimation *animations, unsigned int count); // Unload animation array data
RLAPI void UnloadModelAnimations(ModelAnimation *animations, int animCount); // Unload animation array data
RLAPI bool IsModelAnimationValid(Model model, ModelAnimation anim); // Check model animation skeleton match
// Collision detection functions

View File

@ -15,6 +15,7 @@
* - Functions use always a "result" variable for return
* - Functions are always defined inline
* - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience)
* - No compound literals used to make sure libray is compatible with C++
*
* CONFIGURATION:
* #define RAYMATH_IMPLEMENTATION
@ -713,6 +714,40 @@ RMAPI Vector3 Vector3Normalize(Vector3 v)
return result;
}
//Calculate the projection of the vector v1 on to v2
RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2)
{
Vector3 result = { 0 };
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
float mag = v1dv2/v2dv2;
result.x = v2.x*mag;
result.y = v2.y*mag;
result.z = v2.z*mag;
return result;
}
//Calculate the rejection of the vector v1 on to v2
RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2)
{
Vector3 result = { 0 };
float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
float mag = v1dv2/v2dv2;
result.x = v1.x - (v2.x*mag);
result.y = v1.y - (v2.y*mag);
result.z = v1.z - (v2.z*mag);
return result;
}
// Orthonormalize provided vectors
// Makes vectors normalized and orthogonal to each other
// Gram-Schmidt function implementation

View File

@ -184,6 +184,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
//----------------------------------------------------------------------------------
#define CAMERA_MOVE_SPEED 0.09f
#define CAMERA_ROTATION_SPEED 0.03f
#define CAMERA_PAN_SPEED 0.2f
// Camera mouse movement sensitivity
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f // TODO: it should be independant of framerate
@ -435,7 +436,7 @@ void UpdateCamera(Camera *camera, int mode)
bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON));
bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool lockView = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL));
bool rotateUp = (mode == CAMERA_FREE);
bool rotateUp = false;
if (mode == CAMERA_ORBITAL)
{
@ -458,10 +459,23 @@ void UpdateCamera(Camera *camera, int mode)
// Camera movement
if (!IsGamepadAvailable(0))
{
// Mouse/Keyboard support
// Camera pan (for CAMERA_FREE)
if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE)))
{
const Vector2 mouseDelta = GetMouseDelta();
if (mouseDelta.x > 0.0f) CameraMoveRight(camera, CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -CAMERA_PAN_SPEED, moveInWorldPlane);
if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -CAMERA_PAN_SPEED);
if (mouseDelta.y < 0.0f) CameraMoveUp(camera, CAMERA_PAN_SPEED);
}
else
{
// Mouse support
CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget);
CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp);
}
// Keyboard support
if (IsKeyDown(KEY_W)) CameraMoveForward(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -CAMERA_MOVE_SPEED, moveInWorldPlane);
@ -479,11 +493,14 @@ void UpdateCamera(Camera *camera, int mode)
if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, CAMERA_MOVE_SPEED, moveInWorldPlane);
}
//if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
//if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
if (mode == CAMERA_FREE)
{
if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, CAMERA_MOVE_SPEED);
if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -CAMERA_MOVE_SPEED);
}
}
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL))
if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE))
{
// Zoom target distance
CameraMoveToTarget(camera, -GetMouseWheelMove());

View File

@ -42,9 +42,6 @@
* #define SUPPORT_MOUSE_GESTURES
* Mouse gestures are directly mapped like touches and processed by gestures system.
*
* #define SUPPORT_TOUCH_AS_MOUSE
* Touch input and mouse input are shared. Mouse functions also return touch information.
*
* #define SUPPORT_SSH_KEYBOARD_RPI (Raspberry Pi only)
* Reconfigure standard input to receive key inputs, works with SSH connection.
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other
@ -425,6 +422,8 @@ typedef struct CoreData {
int exitKey; // Default exit key
char currentKeyState[MAX_KEYBOARD_KEYS]; // Registers current frame key state
char previousKeyState[MAX_KEYBOARD_KEYS]; // Registers previous frame key state
// NOTE: Since key press logic involves comparing prev vs cur key state, we need to handle key repeats specially
char keyRepeatInFrame[MAX_KEYBOARD_KEYS]; // Registers key repeats for current frame.
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
int keyPressedQueueCount; // Input keys queue count
@ -491,7 +490,7 @@ typedef struct CoreData {
double frame; // Time measure for one frame
double target; // Desired time for one frame, if 0 not applied
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_DRM)
unsigned long long base; // Base time measure for hi-res timer
unsigned long long int base; // Base time measure for hi-res timer
#endif
unsigned int frameCounter; // Frame counter
} Time;
@ -586,7 +585,7 @@ static const char *autoEventTypeName[] = {
"ACTION_SETTARGETFPS"
};
// Automation Event (24 bytes)
// Automation event (24 bytes)
typedef struct AutomationEvent {
unsigned int frame; // Event frame
unsigned int type; // Event type (AutomationEventType)
@ -870,9 +869,19 @@ void InitWindow(int width, int height, const char *title)
// WARNING: External function: Module required: rtext
LoadFontDefault();
#if defined(SUPPORT_MODULE_RSHAPES)
// Set font white rectangle for shapes drawing, so shapes and text can be batched together
// WARNING: rshapes module is required, if not available, default internal white rectangle is used
Rectangle rec = GetFontDefault().recs[95];
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 }); // WARNING: Module required: rshapes
if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
{
// NOTE: We try to maxime rec padding to avoid pixel bleeding on MSAA filtering
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 2, rec.y + 2, 1, 1 });
}
else
{
// NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding
SetShapesTexture(GetFontDefault().texture, (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 });
}
#endif
#else
#if defined(SUPPORT_MODULE_RSHAPES)
@ -2133,7 +2142,7 @@ void SetClipboardText(const char *text)
#if defined(PLATFORM_WEB)
// Security check to (partially) avoid malicious code
if (strchr(text, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided Clipboard could be potentially malicious, avoid [\'] character");
else emscripten_run_script(TextFormat("navigator.clipboard.writeText('%s')", text));
else EM_ASM( { navigator.clipboard.writeText(UTF8ToString($0)); }, text);
#endif
}
@ -2982,7 +2991,7 @@ int GetFPS(void)
#if !defined(SUPPORT_CUSTOM_FRAME_CONTROL)
#define FPS_CAPTURE_FRAMES_COUNT 30 // 30 captures
#define FPS_AVERAGE_TIME_SECONDS 0.5f // 500 millisecondes
#define FPS_AVERAGE_TIME_SECONDS 0.5f // 500 milliseconds
#define FPS_STEP (FPS_AVERAGE_TIME_SECONDS/FPS_CAPTURE_FRAMES_COUNT)
static int index = 0;
@ -3176,12 +3185,23 @@ int GetFileLength(const char *fileName)
{
int size = 0;
// NOTE: On Unix-like systems, it can by used the POSIX system call: stat(),
// but depending on the platform that call could not be available
//struct stat result = { 0 };
//stat(fileName, &result);
//return result.st_size;
FILE *file = fopen(fileName, "rb");
if (file != NULL)
{
fseek(file, 0L, SEEK_END);
size = (int)ftell(file);
long int fileSize = ftell(file);
// Check for size overflow (INT_MAX)
if (fileSize > 2147483647) TRACELOG(LOG_WARNING, "[%s] File size overflows expected limit, do not use GetFileLength()", fileName);
else size = (int)fileSize;
fclose(file);
}
@ -3478,10 +3498,10 @@ bool ChangeDirectory(const char *dir)
// Check if a given path point to a file
bool IsPathFile(const char *path)
{
struct stat pathStat = { 0 };
stat(path, &pathStat);
struct stat result = { 0 };
stat(path, &result);
return S_ISREG(pathStat.st_mode);
return S_ISREG(result.st_mode);
}
// Check if a file has been dropped into window
@ -3679,7 +3699,7 @@ unsigned char *DecodeDataBase64(const unsigned char *data, int *outputSize)
// Ref: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url)
{
// Security check to (aprtially) avoid malicious code on PLATFORM_WEB
// Security check to (partially) avoid malicious code on PLATFORM_WEB
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character");
else
{
@ -3733,6 +3753,7 @@ void OpenURL(const char *url)
// Check if a key has been pressed once
bool IsKeyPressed(int key)
{
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
bool pressed = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 0) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
@ -3740,9 +3761,18 @@ bool IsKeyPressed(int key)
return pressed;
}
// Check if a key has been pressed again (only PLATFORM_DESKTOP)
bool IsKeyPressedRepeat(int key)
{
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
if (CORE.Input.Keyboard.keyRepeatInFrame[key] == 1) return true;
else return false;
}
// Check if a key is being pressed (key held down)
bool IsKeyDown(int key)
{
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
if (CORE.Input.Keyboard.currentKeyState[key] == 1) return true;
else return false;
}
@ -3750,6 +3780,7 @@ bool IsKeyDown(int key)
// Check if a key has been released once
bool IsKeyReleased(int key)
{
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
bool released = false;
if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
@ -3760,6 +3791,7 @@ bool IsKeyReleased(int key)
// Check if a key is NOT being pressed (key not held down)
bool IsKeyUp(int key)
{
if ((key < 0) || (key >= MAX_KEYBOARD_KEYS)) return false;
if (CORE.Input.Keyboard.currentKeyState[key] == 0) return true;
else return false;
}
@ -4001,7 +4033,7 @@ Vector2 GetMousePosition(void)
{
Vector2 position = { 0 };
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
#if defined(PLATFORM_ANDROID) //|| defined(PLATFORM_WEB)
position = GetTouchPosition(0);
#else
position.x = (CORE.Input.Mouse.currentPosition.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x;
@ -4262,9 +4294,9 @@ static bool InitGraphicsDevice(int width, int height)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
#if defined(__APPLE__)
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires fordward compatibility
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires forward compatibility
#else
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Forward Compatibility Hint: Only 3.3 and above!
#endif
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
}
@ -4446,13 +4478,16 @@ static bool InitGraphicsDevice(int width, int height)
#endif
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
// NOTE: V-Sync can be enabled by graphic driver configuration
// NOTE: V-Sync can be enabled by graphic driver configuration, it doesn't need
// to be activated on web platforms since VSync is enforced there.
#if !defined(PLATFORM_WEB)
if (CORE.Window.flags & FLAG_VSYNC_HINT)
{
// WARNING: It seems to hit a critical render path in Intel HD Graphics
glfwSwapInterval(1);
TRACELOG(LOG_INFO, "DISPLAY: Trying to enable VSYNC");
}
#endif
int fbWidth = CORE.Window.screen.width;
int fbHeight = CORE.Window.screen.height;
@ -5092,6 +5127,8 @@ void PollInputEvents(void)
// Reset keys/chars pressed registered
CORE.Input.Keyboard.keyPressedQueueCount = 0;
CORE.Input.Keyboard.charPressedQueueCount = 0;
// Reset key repeats
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
// Reset last gamepad button/axis registered state
CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN
@ -5099,7 +5136,11 @@ void PollInputEvents(void)
#if defined(PLATFORM_DRM)
// Register previous keys states
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
{
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
PollKeyboardEvents();
@ -5128,7 +5169,11 @@ void PollInputEvents(void)
// Keyboard/Mouse input polling (automatically managed by GLFW3 through callback)
// Register previous keys states
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
{
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
// Register previous mouse states
for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
@ -5310,7 +5355,11 @@ void PollInputEvents(void)
#if defined(PLATFORM_ANDROID)
// Register previous keys states
// NOTE: Android supports up to 260 keys
for (int i = 0; i < 260; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
for (int i = 0; i < 260; i++)
{
CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
// Android ALooper_pollAll() variables
int pollResult = 0;
@ -5506,7 +5555,8 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
// WARNING: GLFW could return GLFW_REPEAT, we need to consider it as 1
// to work properly with our implementation (IsKeyDown/IsKeyUp checks)
if (action == GLFW_RELEASE) CORE.Input.Keyboard.currentKeyState[key] = 0;
else CORE.Input.Keyboard.currentKeyState[key] = 1;
else if(action == GLFW_PRESS) CORE.Input.Keyboard.currentKeyState[key] = 1;
else if(action == GLFW_REPEAT) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
#if !defined(PLATFORM_WEB)
// WARNING: Check if CAPS/NUM key modifiers are enabled and force down state for those keys
@ -5810,7 +5860,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
} break;
case APP_CMD_TERM_WINDOW:
{
// Dettach OpenGL context and destroy display surface
// Detach OpenGL context and destroy display surface
// NOTE 1: This case is used when the user exits the app without closing it. We detach the context to ensure everything is recoverable upon resuming.
// NOTE 2: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
// NOTE 3: In some cases (too many context loaded), OS could unload context automatically... :(
@ -5974,6 +6024,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
CORE.Input.Keyboard.keyPressedQueueCount++;
}
else if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_MULTIPLE) CORE.Input.Keyboard.keyRepeatInFrame[keycode] = 1;
else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
if (keycode == AKEYCODE_POWER)
@ -6277,7 +6328,11 @@ static void ProcessKeyboard(void)
bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call
// Reset pressed keys array (it will be filled below)
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
{
CORE.Input.Keyboard.currentKeyState[i] = 0;
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
// Fill all read bytes (looking for keys)
for (int i = 0; i < bufferByteCount; i++)
@ -6393,7 +6448,11 @@ static void InitEvdevInput(void)
}
// Reset keyboard key state
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
for (int i = 0; i < MAX_KEYBOARD_KEYS; i++)
{
CORE.Input.Keyboard.currentKeyState[i] = 0;
CORE.Input.Keyboard.keyRepeatInFrame[i] = 0;
}
// Open the linux directory of "/dev/input"
directory = opendir(DEFAULT_EVDEV_PATH);
@ -6495,7 +6554,7 @@ static void ConfigureEvdevDevice(char *device)
{
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits);
// Check for absolute movement support (usualy touchscreens, but also joysticks)
// Check for absolute movement support (usually touchscreens, but also joysticks)
if (TEST_BIT(absBits, ABS_X) && TEST_BIT(absBits, ABS_Y))
{
hasAbs = true;
@ -6509,7 +6568,7 @@ static void ConfigureEvdevDevice(char *device)
worker->absRange.height = absinfo.maximum - absinfo.minimum;
}
// Check for multiple absolute movement support (usualy multitouch touchscreens)
// Check for multiple absolute movement support (usually multitouch touchscreens)
if (TEST_BIT(absBits, ABS_MT_POSITION_X) && TEST_BIT(absBits, ABS_MT_POSITION_Y))
{
hasAbsMulti = true;
@ -6524,7 +6583,7 @@ static void ConfigureEvdevDevice(char *device)
}
}
// Check for relative movement support (usualy mouse)
// Check for relative movement support (usually mouse)
if (TEST_BIT(evBits, EV_REL))
{
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBits)), relBits);
@ -6532,7 +6591,7 @@ static void ConfigureEvdevDevice(char *device)
if (TEST_BIT(relBits, REL_X) && TEST_BIT(relBits, REL_Y)) hasRel = true;
}
// Check for button support to determine the device type(usualy on all input devices)
// Check for button support to determine the device type(usually on all input devices)
if (TEST_BIT(evBits, EV_KEY))
{
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits);
@ -6660,7 +6719,7 @@ static void PollKeyboardEvents(void)
// Keyboard button parsing
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
{
keycode = keymapUS[event.code & 0xFF]; // The code we get is a scancode so we look up the apropriate keycode
keycode = keymapUS[event.code & 0xFF]; // The code we get is a scancode so we look up the appropriate keycode
// Make sure we got a valid keycode
if ((keycode > 0) && (keycode < sizeof(CORE.Input.Keyboard.currentKeyState)))
@ -6737,8 +6796,8 @@ static void *EventThread(void *arg)
// Basic movement
if (event.code == ABS_X)
{
CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
CORE.Input.Mouse.currentPosition.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
CORE.Input.Touch.position[0].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
@ -6746,8 +6805,8 @@ static void *EventThread(void *arg)
if (event.code == ABS_Y)
{
CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
CORE.Input.Mouse.currentPosition.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
CORE.Input.Touch.position[0].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
touchAction = 2; // TOUCH_ACTION_MOVE
gestureUpdate = true;
@ -6758,12 +6817,12 @@ static void *EventThread(void *arg)
if (event.code == ABS_MT_POSITION_X)
{
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale according to absRange
}
if (event.code == ABS_MT_POSITION_Y)
{
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale according to absRange
}
if (event.code == ABS_MT_TRACKING_ID)

View File

@ -3267,11 +3267,17 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
case RL_PIXELFORMAT_UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
case RL_PIXELFORMAT_UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
#if defined(GRAPHICS_API_OPENGL_21)
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
#else // defined(GRAPHICS_API_OPENGL_ES2)
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
#endif
#endif
#endif
#elif defined(GRAPHICS_API_OPENGL_33)
case RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
case RL_PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA: *glInternalFormat = GL_RG8; *glFormat = GL_RG; *glType = GL_UNSIGNED_BYTE; break;
@ -4544,6 +4550,7 @@ static void rlLoadShaderDefault(void)
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
"attribute vec3 vertexPosition; \n"
"attribute vec2 vertexTexCoord; \n"
"attribute vec4 vertexColor; \n"

View File

@ -101,7 +101,7 @@
#define PAR_REALLOC(T, BUF, N) ((T*)RL_REALLOC(BUF, sizeof(T)*(N)))
#define PAR_FREE RL_FREE
#if defined(_MSC_VER ) // par shapes has 2 warnings on windows, so disable them just fof this file
#if defined(_MSC_VER) // Disable some MSVC warning
#pragma warning(push)
#pragma warning(disable : 4244)
#pragma warning(disable : 4305)
@ -110,10 +110,9 @@
#define PAR_SHAPES_IMPLEMENTATION
#include "external/par_shapes.h" // Shapes 3d parametric generation
#if defined(_MSC_VER ) // disable MSVC warning suppression for par shapes
#pragma warning( pop )
#if defined(_MSC_VER)
#pragma warning(pop) // Disable MSVC warning suppression
#endif
#endif
#if defined(_WIN32)
@ -152,18 +151,18 @@ static Model LoadOBJ(const char *fileName); // Load OBJ mesh data
#endif
#if defined(SUPPORT_FILEFORMAT_IQM)
static Model LoadIQM(const char *fileName); // Load IQM mesh data
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount); // Load IQM animation data
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount); // Load IQM animation data
#endif
#if defined(SUPPORT_FILEFORMAT_GLTF)
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount); // Load GLTF animation data
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount); // Load GLTF animation data
#endif
#if defined(SUPPORT_FILEFORMAT_VOX)
static Model LoadVOX(const char *filename); // Load VOX mesh data
#endif
#if defined(SUPPORT_FILEFORMAT_M3D)
static Model LoadM3D(const char *filename); // Load M3D mesh data
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount); // Load M3D animation data
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount); // Load M3D animation data
#endif
#if defined(SUPPORT_FILEFORMAT_OBJ) || defined(SUPPORT_FILEFORMAT_MTL)
static void ProcessMaterialsOBJ(Material *rayMaterials, tinyobj_material_t *materials, int materialCount); // Process obj materials
@ -1905,7 +1904,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
int result = tinyobj_parse_mtl_file(&mats, &count, fileName);
if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName);
materials = MemAlloc(count*sizeof(Material));
materials = RL_MALLOC(count*sizeof(Material));
ProcessMaterialsOBJ(materials, mats, count);
tinyobj_materials_free(mats, count);
@ -1980,7 +1979,7 @@ void SetModelMeshMaterial(Model *model, int meshId, int materialId)
}
// Load model animations from file
ModelAnimation *LoadModelAnimations(const char *fileName, unsigned int *animCount)
ModelAnimation *LoadModelAnimations(const char *fileName, int *animCount)
{
ModelAnimation *animations = NULL;
@ -2100,9 +2099,9 @@ void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
}
// Unload animation array data
void UnloadModelAnimations(ModelAnimation *animations, unsigned int count)
void UnloadModelAnimations(ModelAnimation *animations, int animCount)
{
for (unsigned int i = 0; i < count; i++) UnloadModelAnimation(animations[i]);
for (int i = 0; i < animCount; i++) UnloadModelAnimation(animations[i]);
RL_FREE(animations);
}
@ -2458,7 +2457,7 @@ Mesh GenMeshCube(float width, float height, float length)
// Platonic solids:
par_shapes_mesh* par_shapes_create_tetrahedron(); // 4 sides polyhedron (pyramid)
par_shapes_mesh* par_shapes_create_cube(); // 6 sides polyhedron (cube)
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (dyamond)
par_shapes_mesh* par_shapes_create_octahedron(); // 8 sides polyhedron (diamond)
par_shapes_mesh* par_shapes_create_dodecahedron(); // 12 sides polyhedron
par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
*/
@ -4082,8 +4081,8 @@ static Model LoadIQM(const char *fileName)
#define MESH_NAME_LENGTH 32 // Mesh name string length
#define MATERIAL_NAME_LENGTH 32 // Material name string length
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
unsigned char *fileDataPtr = fileData;
// IQM file structs
@ -4091,7 +4090,7 @@ static Model LoadIQM(const char *fileName)
typedef struct IQMHeader {
char magic[16];
unsigned int version;
unsigned int filesize;
unsigned int dataSize;
unsigned int flags;
unsigned int num_text, ofs_text;
unsigned int num_meshes, ofs_meshes;
@ -4245,7 +4244,7 @@ static Model LoadIQM(const char *fileName)
model.meshes[i].triangleCount = imesh[i].num_triangles;
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
// Animated verted data, what we actually process for rendering
// Animated vertex data, what we actually process for rendering
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
@ -4444,19 +4443,19 @@ static Model LoadIQM(const char *fileName)
}
// Load IQM animation data
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, unsigned int *animCount)
static ModelAnimation *LoadModelAnimationsIQM(const char *fileName, int *animCount)
{
#define IQM_MAGIC "INTERQUAKEMODEL" // IQM file magic number
#define IQM_VERSION 2 // only IQM version 2 supported
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
unsigned char *fileDataPtr = fileData;
typedef struct IQMHeader {
char magic[16];
unsigned int version;
unsigned int filesize;
unsigned int dataSize;
unsigned int flags;
unsigned int num_text, ofs_text;
unsigned int num_meshes, ofs_meshes;
@ -4705,7 +4704,7 @@ static Image LoadImageFromCgltfImage(cgltf_image *cgltfImage, const char *texPat
if (result == cgltf_result_success)
{
image = LoadImageFromMemory(".png", (unsigned char *)data, outSize);
MemFree(data);
RL_FREE(data);
}
}
}
@ -4788,7 +4787,7 @@ static Model LoadGLTF(const char *fileName)
RESTRICTIONS:
- Only triangle meshes supported
- Vertex attibute types and formats supported:
- Vertex attribute types and formats supported:
> Vertices (position): vec3: float
> Normals: vec3: float
> Texcoords: vec2: float
@ -4816,7 +4815,7 @@ static Model LoadGLTF(const char *fileName)
Model model = { 0 };
// glTF file loading
unsigned int dataSize = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData == NULL) return model;
@ -5287,7 +5286,7 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
Vector4 v2 = {tmp[0], tmp[1], tmp[2], tmp[3]};
Vector4 *r = data;
// Only v4 is for rotations, so we know it's a quat
// Only v4 is for rotations, so we know it's a quaternion
*r = QuaternionSlerp(v1, v2, t);
}
@ -5296,10 +5295,10 @@ static bool GetPoseAtTimeGLTF(cgltf_accessor *input, cgltf_accessor *output, flo
#define GLTF_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, unsigned int *animCount)
static ModelAnimation *LoadModelAnimationsGLTF(const char *fileName, int *animCount)
{
// glTF file loading
unsigned int dataSize = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
ModelAnimation *animations = NULL;
@ -5467,11 +5466,11 @@ static Model LoadVOX(const char *fileName)
int nbvertices = 0;
int meshescount = 0;
unsigned int fileSize = 0;
unsigned char *fileData = NULL;
// Read vox file into buffer
fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData == 0)
{
TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load VOX file", fileName);
@ -5480,7 +5479,7 @@ static Model LoadVOX(const char *fileName)
// Read and build voxarray description
VoxArray3D voxarray = { 0 };
int ret = Vox_LoadFromMemory(fileData, fileSize, &voxarray);
int ret = Vox_LoadFromMemory(fileData, dataSize, &voxarray);
if (ret != VOX_SUCCESS)
{
@ -5575,9 +5574,10 @@ static Model LoadM3D(const char *fileName)
m3d_t *m3d = NULL;
m3dp_t *prop = NULL;
unsigned int bytesRead = 0;
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
int i, j, k, l, n, mi = -2;
int i, j, k, l, n, mi = -2, vcolor = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData != NULL)
{
@ -5607,10 +5607,13 @@ static Model LoadM3D(const char *fileName)
}
else
{
model.meshCount = model.materialCount = 1;
model.meshCount = 1; model.materialCount = 0;
TRACELOG(LOG_INFO, "MODEL: No materials, putting all meshes in a default material");
}
// We always need a default material, so we add +1
model.materialCount++;
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
model.materials = (Material *)RL_CALLOC(model.materialCount + 1, sizeof(Material));
@ -5635,7 +5638,14 @@ static Model LoadM3D(const char *fileName)
k++;
mi = m3d->face[i].materialid;
for (j = i, l = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++);
// Only allocate colors VertexBuffer if there's a color vertex in the model for this material batch
// if all colors are fully transparent black for all verteces of this materal, then we assume no vertex colors
for (j = i, l = vcolor = 0; (j < (int)m3d->numface) && (mi == m3d->face[j].materialid); j++, l++)
{
if (!m3d->vertex[m3d->face[j].vertex[0]].color ||
!m3d->vertex[m3d->face[j].vertex[1]].color ||
!m3d->vertex[m3d->face[j].vertex[2]].color) vcolor = 1;
}
model.meshes[k].vertexCount = l*3;
model.meshes[k].triangleCount = l;
@ -5643,9 +5653,9 @@ static Model LoadM3D(const char *fileName)
model.meshes[k].texcoords = (float *)RL_CALLOC(model.meshes[k].vertexCount*2, sizeof(float));
model.meshes[k].normals = (float *)RL_CALLOC(model.meshes[k].vertexCount*3, sizeof(float));
// If no map is provided, we allocate storage for vertex colors
// M3D specs only consider vertex colors if no material is provided
if (mi != M3D_UNDEF) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
// If no map is provided, or we have colors defined, we allocate storage for vertex colors
// M3D specs only consider vertex colors if no material is provided, however raylib uses both and mixes the colors
if ((mi == M3D_UNDEF) || vcolor) model.meshes[k].colors = RL_CALLOC(model.meshes[k].vertexCount*4, sizeof(unsigned char));
if (m3d->numbone && m3d->numskin)
{
@ -5869,16 +5879,17 @@ static Model LoadM3D(const char *fileName)
#define M3D_ANIMDELAY 17 // Animation frames delay, (~1000 ms/60 FPS = 16.666666* ms)
// Load M3D animation data
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, unsigned int *animCount)
static ModelAnimation *LoadModelAnimationsM3D(const char *fileName, int *animCount)
{
m3d_t *m3d = NULL;
unsigned int bytesRead = 0;
unsigned char *fileData = LoadFileData(fileName, &bytesRead);
ModelAnimation *animations = NULL;
int i = 0, j = 0;
m3d_t *m3d = NULL;
int i = 0, j = 0;
*animCount = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData != NULL)
{
m3d = m3d_load(fileData, m3d_loaderhook, m3d_freehook, NULL);

View File

@ -67,8 +67,8 @@
#ifndef SMOOTH_CIRCLE_ERROR_RATE
#define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
#endif
#ifndef BEZIER_LINE_DIVISIONS
#define BEZIER_LINE_DIVISIONS 24 // Bezier line divisions
#ifndef SPLINE_LINE_DIVISIONS
#define SPLINE_LINE_DIVISIONS 24 // Spline lines segment divisions
#endif
@ -99,7 +99,7 @@ void SetShapesTexture(Texture2D texture, Rectangle source)
{
// Reset texture to default pixel if required
// WARNING: Shapes texture should be probably better validated,
// it can break the rendering of all shapes if missused
// it can break the rendering of all shapes if misused
if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
{
texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
@ -190,6 +190,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
if ((length > 0) && (thick > 0))
{
float scale = thick/(2*length);
Vector2 radius = { -scale*delta.y, scale*delta.x };
Vector2 strip[4] = {
{ startPos.x - radius.x, startPos.y - radius.y },
@ -208,14 +209,14 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
Vector2 previous = startPos;
Vector2 current = { 0 };
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
{
// Cubic easing in-out
// NOTE: Easing is calculated only for y position value
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS);
current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS;
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)SPLINE_LINE_DIVISIONS);
current.x = previous.x + (endPos.x - startPos.x)/(float)SPLINE_LINE_DIVISIONS;
float dy = current.y - previous.y;
float dx = current.x - previous.x;
@ -237,25 +238,26 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
previous = current;
}
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
}
// Draw line using quadratic bezier curves with a control point
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
{
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
Vector2 previous = startPos;
Vector2 current = { 0 };
float t = 0.0f;
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
{
t = step*i;
float a = powf(1 - t, 2);
float b = 2*(1 - t)*t;
float a = powf(1.0f - t, 2);
float b = 2.0f*(1.0f - t)*t;
float c = powf(t, 2);
// NOTE: The easing functions aren't suitable here because they don't take a control point
@ -282,26 +284,27 @@ void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, fl
previous = current;
}
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
}
// Draw line using cubic bezier curves with 2 control points
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
{
const float step = 1.0f/BEZIER_LINE_DIVISIONS;
const float step = 1.0f/SPLINE_LINE_DIVISIONS;
Vector2 previous = startPos;
Vector2 current = { 0 };
float t = 0.0f;
Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 };
Vector2 points[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
for (int i = 1; i <= SPLINE_LINE_DIVISIONS; i++)
{
t = step*i;
float a = powf(1 - t, 3);
float b = 3*powf(1 - t, 2)*t;
float c = 3*(1-t)*powf(t, 2);
float a = powf(1.0f - t, 3);
float b = 3.0f*powf(1.0f - t, 2)*t;
float c = 3.0f*(1.0f - t)*powf(t, 2);
float d = powf(t, 3);
current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
@ -327,7 +330,149 @@ void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlP
previous = current;
}
DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color);
DrawTriangleStrip(points, 2*SPLINE_LINE_DIVISIONS + 2, color);
}
// Draw a B-Spline line, minimum 4 points
void DrawLineBSpline(Vector2 *points, int pointCount, float thick, Color color)
{
if (pointCount < 4) return;
float a[4] = { 0 };
float b[4] = { 0 };
float dy = 0.0f;
float dx = 0.0f;
float size = 0.0f;
Vector2 currentPoint = { 0 };
Vector2 nextPoint = { 0 };
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
for (int i = 0; i < (pointCount - 3); i++)
{
float t = 0.0f;
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
a[0] = (-p1.x + 3.0f*p2.x - 3.0f*p3.x + p4.x)/6.0f;
a[1] = (3.0f*p1.x - 6.0f*p2.x + 3.0f*p3.x)/6.0f;
a[2] = (-3.0f*p1.x + 3.0f*p3.x)/6.0f;
a[3] = (p1.x + 4.0f*p2.x + p3.x)/6.0f;
b[0] = (-p1.y + 3.0f*p2.y - 3.0f*p3.y + p4.y)/6.0f;
b[1] = (3.0f*p1.y - 6.0f*p2.y + 3.0f*p3.y)/6.0f;
b[2] = (-3.0f*p1.y + 3.0f*p3.y)/6.0f;
b[3] = (p1.y + 4.0f*p2.y + p3.y)/6.0f;
currentPoint.x = a[3];
currentPoint.y = b[3];
if (i == 0) DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
if (i > 0)
{
vertices[0].x = currentPoint.x + dy*size;
vertices[0].y = currentPoint.y - dx*size;
vertices[1].x = currentPoint.x - dy*size;
vertices[1].y = currentPoint.y + dx*size;
}
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
{
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
nextPoint.x = a[3] + t*(a[2] + t*(a[1] + t*a[0]));
nextPoint.y = b[3] + t*(b[2] + t*(b[1] + t*b[0]));
dy = nextPoint.y - currentPoint.y;
dx = nextPoint.x - currentPoint.x;
size = 0.5f*thick/sqrtf(dx*dx+dy*dy);
if ((i == 0) && (j == 1))
{
vertices[0].x = currentPoint.x + dy*size;
vertices[0].y = currentPoint.y - dx*size;
vertices[1].x = currentPoint.x - dy*size;
vertices[1].y = currentPoint.y + dx*size;
}
vertices[2*j + 1].x = nextPoint.x - dy*size;
vertices[2*j + 1].y = nextPoint.y + dx*size;
vertices[2*j].x = nextPoint.x + dy*size;
vertices[2*j].y = nextPoint.y - dx*size;
currentPoint = nextPoint;
}
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
}
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
}
// Draw a Catmull Rom spline line, minimum 4 points
void DrawLineCatmullRom(Vector2 *points, int pointCount, float thick, Color color)
{
if (pointCount < 4) return;
float dy = 0.0f;
float dx = 0.0f;
float size = 0.0f;
Vector2 currentPoint = points[1];
Vector2 nextPoint = { 0 };
Vector2 vertices[2*SPLINE_LINE_DIVISIONS + 2] = { 0 };
DrawCircleV(currentPoint, thick/2.0f, color); // Draw init line circle-cap
for (int i = 0; i < (pointCount - 3); i++)
{
float t = 0.0f;
Vector2 p1 = points[i], p2 = points[i + 1], p3 = points[i + 2], p4 = points[i + 3];
if (i > 0)
{
vertices[0].x = currentPoint.x + dy*size;
vertices[0].y = currentPoint.y - dx*size;
vertices[1].x = currentPoint.x - dy*size;
vertices[1].y = currentPoint.y + dx*size;
}
for (int j = 1; j <= SPLINE_LINE_DIVISIONS; j++)
{
t = ((float)j)/((float)SPLINE_LINE_DIVISIONS);
float q0 = (-1.0f*t*t*t) + (2.0f*t*t) + (-1.0f*t);
float q1 = (3.0f*t*t*t) + (-5.0f*t*t) + 2.0f;
float q2 = (-3.0f*t*t*t) + (4.0f*t*t) + t;
float q3 = t*t*t - t*t;
nextPoint.x = 0.5f*((p1.x*q0) + (p2.x*q1) + (p3.x*q2) + (p4.x*q3));
nextPoint.y = 0.5f*((p1.y*q0) + (p2.y*q1) + (p3.y*q2) + (p4.y*q3));
dy = nextPoint.y - currentPoint.y;
dx = nextPoint.x - currentPoint.x;
size = (0.5f*thick)/sqrtf(dx*dx + dy*dy);
if ((i == 0) && (j == 1))
{
vertices[0].x = currentPoint.x + dy*size;
vertices[0].y = currentPoint.y - dx*size;
vertices[1].x = currentPoint.x - dy*size;
vertices[1].y = currentPoint.y + dx*size;
}
vertices[2*j + 1].x = nextPoint.x - dy*size;
vertices[2*j + 1].y = nextPoint.y + dx*size;
vertices[2*j].x = nextPoint.x + dy*size;
vertices[2*j].y = nextPoint.y - dx*size;
currentPoint = nextPoint;
}
DrawTriangleStrip(vertices, 2*SPLINE_LINE_DIVISIONS + 2, color);
}
DrawCircleV(currentPoint, thick/2.0f, color); // Draw end line circle-cap
}
// Draw lines sequence
@ -353,6 +498,13 @@ void DrawCircle(int centerX, int centerY, float radius, Color color)
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
}
// Draw a color-filled circle (Vector version)
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
void DrawCircleV(Vector2 center, float radius, Color color)
{
DrawCircleSector(center, radius, 0, 360, 36, color);
}
// Draw a piece of a circle
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
{
@ -385,6 +537,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
rlSetTexture(texShapes.id);
rlBegin(RL_QUADS);
// NOTE: Every QUAD actually represents two segments
for (int i = 0; i < segments/2; i++)
{
@ -394,7 +547,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
rlVertex2f(center.x, center.y);
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2.0f))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2.0f))*radius);
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
@ -402,11 +555,11 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
angle += (stepLength*2);
angle += (stepLength*2.0f);
}
// NOTE: In case number of segments is odd, we add one last piece to the cake
if (segments%2)
if ((segments%2) == 1)
{
rlColor4ub(color.r, color.g, color.b, color.a);
@ -422,6 +575,7 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
rlVertex2f(center.x, center.y);
}
rlEnd();
rlSetTexture(0);
@ -514,13 +668,6 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
rlEnd();
}
// Draw a color-filled circle (Vector version)
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
void DrawCircleV(Vector2 center, float radius, Color color)
{
DrawCircleSector(center, radius, 0, 360, 36, color);
}
// Draw circle outline
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
{

View File

@ -71,12 +71,21 @@
#include <ctype.h> // Required for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
#if defined(SUPPORT_FILEFORMAT_TTF)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define STB_RECT_PACK_IMPLEMENTATION
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
#define STBTT_STATIC
#define STB_TRUETYPE_IMPLEMENTATION
#include "external/stb_truetype.h" // Required for: ttf font data reading
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic pop
#endif
#endif
//----------------------------------------------------------------------------------
@ -349,18 +358,18 @@ Font LoadFont(const char *fileName)
// Load Font from TTF font file with generation parameters
// NOTE: You can pass an array with desired characters, those characters should be available in the font
// if array is NULL, default char set is selected 32..126
Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount)
Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount)
{
Font font = { 0 };
// Loading file to memory
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData != NULL)
{
// Loading font from memory data
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, glyphCount);
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, dataSize, fontSize, codepoints, codepointCount);
UnloadFileData(fileData);
}
@ -495,7 +504,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
}
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf"
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount)
Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount)
{
Font font = { 0 };
@ -507,9 +516,9 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
TextIsEqual(fileExtLower, ".otf"))
{
font.baseSize = fontSize;
font.glyphCount = (glyphCount > 0)? glyphCount : 95;
font.glyphCount = (codepointCount > 0)? codepointCount : 95;
font.glyphPadding = 0;
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.glyphCount, FONT_DEFAULT);
font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, codepoints, font.glyphCount, FONT_DEFAULT);
if (font.glyphs != NULL)
{
@ -553,7 +562,7 @@ bool IsFontReady(Font font)
// Load font data for further use
// NOTE: Requires TTF font memory data and can generate SDF data
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type)
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *codepoints, int codepointCount, int type)
{
// NOTE: Using some SDF generation default values,
// trades off precision with ability to handle *smaller* sizes
@ -591,25 +600,25 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
// In case no chars count provided, default to 95
glyphCount = (glyphCount > 0)? glyphCount : 95;
codepointCount = (codepointCount > 0)? codepointCount : 95;
// Fill fontChars in case not provided externally
// NOTE: By default we fill glyphCount consecutively, starting at 32 (Space)
if (fontChars == NULL)
if (codepoints == NULL)
{
fontChars = (int *)RL_MALLOC(glyphCount*sizeof(int));
for (int i = 0; i < glyphCount; i++) fontChars[i] = i + 32;
codepoints = (int *)RL_MALLOC(codepointCount*sizeof(int));
for (int i = 0; i < codepointCount; i++) codepoints[i] = i + 32;
genFontChars = true;
}
chars = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
chars = (GlyphInfo *)RL_MALLOC(codepointCount*sizeof(GlyphInfo));
// NOTE: Using simple packaging, one char after another
for (int i = 0; i < glyphCount; i++)
for (int i = 0; i < codepointCount; i++)
{
int chw = 0, chh = 0; // Character width and height (on generation)
int ch = fontChars[i]; // Character value to get info for
int ch = codepoints[i]; // Character value to get info for
chars[i].value = ch;
// Render a unicode codepoint to a bitmap
@ -669,7 +678,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
}
else TRACELOG(LOG_WARNING, "FONT: Failed to process TTF font data");
if (genFontChars) RL_FREE(fontChars);
if (genFontChars) RL_FREE(codepoints);
}
#endif
@ -679,17 +688,17 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// Generate image font atlas using chars info
// NOTE: Packing method: 0-Default, 1-Skyline
#if defined(SUPPORT_FILEFORMAT_TTF)
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphCount, int fontSize, int padding, int packMethod)
Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod)
{
Image atlas = { 0 };
if (chars == NULL)
if (glyphs == NULL)
{
TRACELOG(LOG_WARNING, "FONT: Provided chars info not valid, returning empty image atlas");
return atlas;
}
*charRecs = NULL;
*glyphRecs = NULL;
// In case no chars count provided we suppose default of 95
glyphCount = (glyphCount > 0)? glyphCount : 95;
@ -703,8 +712,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
for (int i = 0; i < glyphCount; i++)
{
if (chars[i].image.width > maxGlyphWidth) maxGlyphWidth = chars[i].image.width;
totalWidth += chars[i].image.width + 4*padding;
if (glyphs[i].image.width > maxGlyphWidth) maxGlyphWidth = glyphs[i].image.width;
totalWidth += glyphs[i].image.width + 4*padding;
}
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
@ -755,7 +764,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
for (int i = 0; i < glyphCount; i++)
{
// Check remaining space for glyph
if (offsetX >= (atlas.width - chars[i].image.width - 2*padding))
if (offsetX >= (atlas.width - glyphs[i].image.width - 2*padding))
{
offsetX = padding;
@ -780,22 +789,22 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
}
// Copy pixel data from fc.data to atlas
for (int y = 0; y < chars[i].image.height; y++)
for (int y = 0; y < glyphs[i].image.height; y++)
{
for (int x = 0; x < chars[i].image.width; x++)
for (int x = 0; x < glyphs[i].image.width; x++)
{
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
((unsigned char *)atlas.data)[(offsetY + y)*atlas.width + (offsetX + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
}
}
// Fill chars rectangles in atlas info
recs[i].x = (float)offsetX;
recs[i].y = (float)offsetY;
recs[i].width = (float)chars[i].image.width;
recs[i].height = (float)chars[i].image.height;
recs[i].width = (float)glyphs[i].image.width;
recs[i].height = (float)glyphs[i].image.height;
// Move atlas position X for next character drawing
offsetX += (chars[i].image.width + 2*padding);
offsetX += (glyphs[i].image.width + 2*padding);
}
}
else if (packMethod == 1) // Use Skyline rect packing algorithm (stb_pack_rect)
@ -810,8 +819,8 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
for (int i = 0; i < glyphCount; i++)
{
rects[i].id = i;
rects[i].w = chars[i].image.width + 2*padding;
rects[i].h = chars[i].image.height + 2*padding;
rects[i].w = glyphs[i].image.width + 2*padding;
rects[i].h = glyphs[i].image.height + 2*padding;
}
// Package rectangles into atlas
@ -822,17 +831,17 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
// It returns char rectangles in atlas
recs[i].x = rects[i].x + (float)padding;
recs[i].y = rects[i].y + (float)padding;
recs[i].width = (float)chars[i].image.width;
recs[i].height = (float)chars[i].image.height;
recs[i].width = (float)glyphs[i].image.width;
recs[i].height = (float)glyphs[i].image.height;
if (rects[i].was_packed)
{
// Copy pixel data from fc.data to atlas
for (int y = 0; y < chars[i].image.height; y++)
for (int y = 0; y < glyphs[i].image.height; y++)
{
for (int x = 0; x < chars[i].image.width; x++)
for (int x = 0; x < glyphs[i].image.width; x++)
{
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)chars[i].image.data)[y*chars[i].image.width + x];
((unsigned char *)atlas.data)[(rects[i].y + padding + y)*atlas.width + (rects[i].x + padding + x)] = ((unsigned char *)glyphs[i].image.data)[y*glyphs[i].image.width + x];
}
}
}
@ -870,7 +879,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
atlas.data = dataGrayAlpha;
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAY_ALPHA;
*charRecs = recs;
*glyphRecs = recs;
return atlas;
}
@ -966,7 +975,7 @@ bool ExportFontAsCode(Font font, const char *fileName)
byteCount += sprintf(txtData + byteCount, "static unsigned char fontData_%s[COMPRESSED_DATA_SIZE_FONT_%s] = { ", fileNamePascal, TextToUpper(fileNamePascal));
for (int i = 0; i < compDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%02x,\n " : "0x%02x, "), compData[i]);
byteCount += sprintf(txtData + byteCount, "0x%02x };\n\n", compData[compDataSize - 1]);
MemFree(compData);
RL_FREE(compData);
#else
// Save font image data (uncompressed)
byteCount += sprintf(txtData + byteCount, "// Font image pixels data\n");
@ -1066,7 +1075,7 @@ void DrawFPS(int posX, int posY)
if ((fps < 30) && (fps >= 15)) color = ORANGE; // Warning FPS
else if (fps < 15) color = RED; // Low FPS
DrawText(TextFormat("%2i FPS", GetFPS()), posX, posY, 20, color);
DrawText(TextFormat("%2i FPS", fps), posX, posY, 20, color);
}
// Draw text (using default font)
@ -1167,14 +1176,14 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
}
// Draw multiple character (codepoints)
void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint)
void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint)
{
int textOffsetY = 0; // Offset between lines (on linebreak '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
for (int i = 0; i < count; i++)
for (int i = 0; i < codepointCount; i++)
{
int index = GetGlyphIndex(font, codepoints[i]);
@ -1688,7 +1697,7 @@ const char *TextToPascal(const char *text)
// WARNING: Allocated memory must be manually freed
char *LoadUTF8(const int *codepoints, int length)
{
// We allocate enough memory fo fit all possible codepoints
// We allocate enough memory to fit all possible codepoints
// NOTE: 5 bytes for every codepoint should be enough
char *text = (char *)RL_CALLOC(length*5, 1);
const char *utf8 = NULL;
@ -1757,7 +1766,7 @@ int GetCodepointCount(const char *text)
while (*ptr != '\0')
{
int next = 0;
int letter = GetCodepointNext(ptr, &next);
GetCodepointNext(ptr, &next);
ptr += next;

View File

@ -138,13 +138,24 @@
defined(SUPPORT_FILEFORMAT_PIC) || \
defined(SUPPORT_FILEFORMAT_PNM))
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define STBI_MALLOC RL_MALLOC
#define STBI_FREE RL_FREE
#define STBI_REALLOC RL_REALLOC
#define STBI_NO_THREAD_LOCALS
#define STB_IMAGE_IMPLEMENTATION
#include "external/stb_image.h" // Required for: stbi_load_from_file()
// NOTE: Used to read image data (multiple formats support)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic pop
#endif
#endif
#if (defined(SUPPORT_FILEFORMAT_DDS) || \
@ -153,24 +164,34 @@
defined(SUPPORT_FILEFORMAT_PVR) || \
defined(SUPPORT_FILEFORMAT_ASTC))
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#define RL_GPUTEX_IMPLEMENTATION
#include "external/rl_gputex.h" // Required for: rl_load_xxx_from_memory()
// NOTE: Used to read compressed textures data (multiple formats support)
#if defined(__GNUC__) // GCC and Clang
#pragma GCC diagnostic pop
#endif
#endif
#if defined(SUPPORT_FILEFORMAT_QOI)
#define QOI_MALLOC RL_MALLOC
#define QOI_FREE RL_FREE
#if defined(_MSC_VER ) // qoi has warnings on windows, so disable them just for this file
#if defined(_MSC_VER) // Disable some MSVC warning
#pragma warning(push)
#pragma warning(disable : 4267)
#endif
#define QOI_IMPLEMENTATION
#include "external/qoi.h"
#if defined(_MSC_VER)
#pragma warning( pop )
#pragma warning(pop) // Disable MSVC warning suppression
#endif
#endif
@ -194,6 +215,14 @@
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() [ImageResize()]
#if defined(SUPPORT_FILEFORMAT_SVG)
#define NANOSVG_IMPLEMENTATION // Expands implementation
#include "external/nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "external/nanosvgrast.h"
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@ -250,11 +279,11 @@ Image LoadImage(const char *fileName)
#endif
// Loading file to memory
unsigned int fileSize = 0;
unsigned char *fileData = LoadFileData(fileName, &fileSize);
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
// Loading image from memory data
if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, fileSize);
if (fileData != NULL) image = LoadImageFromMemory(GetFileExtension(fileName), fileData, dataSize);
RL_FREE(fileData);
@ -266,7 +295,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
{
Image image = { 0 };
unsigned int dataSize = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData != NULL)
@ -289,6 +318,82 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
return image;
}
// Load an image from a SVG file or string with custom size
Image LoadImageSvg(const char *fileNameOrString, int width, int height)
{
Image image = { 0 };
bool isSvgStringValid = false;
#if defined(SUPPORT_FILEFORMAT_SVG)
// Validate fileName or string
if (fileNameOrString != NULL)
{
int dataSize = 0;
unsigned char *fileData = NULL;
if (FileExists(fileNameOrString))
{
fileData = LoadFileData(fileNameOrString, &dataSize);
isSvgStringValid = true;
}
else
{
// Validate fileData as valid SVG string data
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
if ((fileNameOrString != NULL) &&
(fileNameOrString[0] == '<') &&
(fileNameOrString[1] == 's') &&
(fileNameOrString[2] == 'v') &&
(fileNameOrString[3] == 'g'))
{
fileData = fileNameOrString;
isSvgStringValid = true;
}
}
if (isSvgStringValid)
{
struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(width*height*4);
// Calculate scales for both the width and the height
const float scaleWidth = width/svgImage->width;
const float scaleHeight = height/svgImage->height;
// Set the largest of the 2 scales to be the scale to use
const float scale = (scaleHeight > scaleWidth)? scaleWidth : scaleHeight;
int offsetX = 0;
int offsetY = 0;
if (scaleHeight > scaleWidth) offsetY = (height - svgImage->height*scale) / 2;
else offsetX = (width - svgImage->width*scale) / 2;
// Rasterize
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
nsvgRasterize(rast, svgImage, (int)offsetX, (int)offsetY, scale, img, width, height, width*4);
// Populate image struct with all data
image.data = img;
image.width = width;
image.height = height;
image.mipmaps = 1;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
// Free used memory
nsvgDelete(svgImage);
}
if (isSvgStringValid && (fileData != fileNameOrString)) UnloadFileData(fileData);
}
#else
TRACELOG(LOG_WARNING, "SVG image support not enabled, image can not be loaded");
#endif
return image;
}
// Load animated image data
// - Image.data buffer includes all frames: [image#0][image#1][image#2][...]
// - Number of frames is returned through 'frames' parameter
@ -302,7 +407,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
#if defined(SUPPORT_FILEFORMAT_GIF)
if (IsFileExtension(fileName, ".gif"))
{
unsigned int dataSize = 0;
int dataSize = 0;
unsigned char *fileData = LoadFileData(fileName, &dataSize);
if (fileData != NULL)
@ -411,6 +516,8 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
#endif
#if defined(SUPPORT_FILEFORMAT_QOI)
else if ((strcmp(fileType, ".qoi") == 0) || (strcmp(fileType, ".QOI") == 0))
{
if (fileData != NULL)
{
qoi_desc desc = { 0 };
image.data = qoi_decode(fileData, dataSize, &desc, 4);
@ -419,6 +526,36 @@ Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, i
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
image.mipmaps = 1;
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_SVG)
else if ((strcmp(fileType, ".svg") == 0) || (strcmp(fileType, ".SVG") == 0))
{
// Validate fileData as valid SVG string data
//<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2484" viewBox="0 0 192.756 191.488">
if ((fileData != NULL) &&
(fileData[0] == '<') &&
(fileData[1] == 's') &&
(fileData[2] == 'v') &&
(fileData[3] == 'g'))
{
struct NSVGimage *svgImage = nsvgParse(fileData, "px", 96.0f);
unsigned char *img = RL_MALLOC(svgImage->width*svgImage->height*4);
// Rasterize
struct NSVGrasterizer *rast = nsvgCreateRasterizer();
nsvgRasterize(rast, svgImage, 0, 0, 1.0f, img, svgImage->width, svgImage->height, svgImage->width*4);
// Populate image struct with all data
image.data = img;
image.width = svgImage->width;
image.height = svgImage->height;
image.mipmaps = 1;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
nsvgDelete(svgImage);
}
}
#endif
#if defined(SUPPORT_FILEFORMAT_DDS)
else if ((strcmp(fileType, ".dds") == 0) || (strcmp(fileType, ".DDS") == 0))
@ -3265,6 +3402,14 @@ void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color)
if (rec.width < 0) rec.width = 0;
if (rec.height < 0) rec.height = 0;
// Clamp the size the the image bounds
if ((rec.x + rec.width) >= dst->width) rec.width = dst->width - rec.x;
if ((rec.y + rec.height) >= dst->height) rec.height = dst->height - rec.y;
// Check if the rect is even inside the image
if ((rec.x > dst->width) || (rec.y > dst->height)) return;
if (((rec.x + rec.width) < 0) || (rec.y + rec.height < 0)) return;
int sy = (int)rec.y;
int sx = (int)rec.x;

View File

@ -180,16 +180,16 @@ void MemFree(void *ptr)
}
// Load data from file into a buffer
unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
unsigned char *LoadFileData(const char *fileName, int *dataSize)
{
unsigned char *data = NULL;
*bytesRead = 0;
*dataSize = 0;
if (fileName != NULL)
{
if (loadFileData)
{
data = loadFileData(fileName, bytesRead);
data = loadFileData(fileName, dataSize);
return data;
}
#if defined(SUPPORT_STANDARD_FILEIO)
@ -211,7 +211,7 @@ unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead)
{
// NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
*bytesRead = count;
*dataSize = count;
if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
@ -239,7 +239,7 @@ void UnloadFileData(unsigned char *data)
}
// Save data to file from buffer
bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
bool SaveFileData(const char *fileName, void *data, int dataSize)
{
bool success = false;
@ -247,17 +247,17 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
{
if (saveFileData)
{
return saveFileData(fileName, data, bytesToWrite);
return saveFileData(fileName, data, dataSize);
}
#if defined(SUPPORT_STANDARD_FILEIO)
FILE *file = fopen(fileName, "wb");
if (file != NULL)
{
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), bytesToWrite, file);
unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
else if (count != bytesToWrite) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
int result = fclose(file);
@ -274,7 +274,7 @@ bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite)
}
// Export data to code (.h), returns true on success
bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName)
bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName)
{
bool success = false;
@ -284,7 +284,7 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
// NOTE: Text data buffer size is estimated considering raw data size in bytes
// and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(size*6 + 2000, sizeof(char));
char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
int byteCount = 0;
byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
@ -303,11 +303,11 @@ bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *
strcpy(varFileName, GetFileNameWithoutExt(fileName));
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, size);
byteCount += sprintf(txtData + byteCount, "#define %s_DATA_SIZE %i\n\n", varFileName, dataSize);
byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%s_DATA_SIZE] = { ", varFileName, varFileName);
for (unsigned int i = 0; i < size - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[size - 1]);
for (int i = 0; i < (dataSize - 1); i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), data[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", data[dataSize - 1]);
// NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData);
@ -465,12 +465,12 @@ FILE *android_fopen(const char *fileName, const char *mode)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
static int android_read(void *cookie, char *buf, int size)
static int android_read(void *cookie, char *data, int dataSize)
{
return AAsset_read((AAsset *)cookie, buf, size);
return AAsset_read((AAsset *)cookie, data, dataSize);
}
static int android_write(void *cookie, const char *buf, int size)
static int android_write(void *cookie, const char *data, int dataSize)
{
TRACELOG(LOG_WARNING, "ANDROID: Failed to provide write access to APK");