This commit is contained in:
fxgen 2021-09-05 17:26:07 +02:00
commit 8410e10578
28 changed files with 1478 additions and 1307 deletions

5
.gitignore vendored
View File

@ -1,11 +1,6 @@
# Ignore generated files # Ignore generated files
# ... # ...
# Ignore all without extensions
*
!*.*
!*/
# Ignore VIM's backup generated files # Ignore VIM's backup generated files
*.swp *.swp
*.swo *.swo

View File

@ -45,6 +45,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| raylib-ruby-ffi | 2.0 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/D3nX/raylib-ruby-ffi | | raylib-ruby-ffi | 2.0 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/D3nX/raylib-ruby-ffi |
| raylib-ruby | 2.6 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/a0/raylib-ruby | | raylib-ruby | 2.6 | [Ruby](https://www.ruby-lang.org/en/) | https://github.com/a0/raylib-ruby |
| raylib-mruby | 2.5-dev | [mruby](https://github.com/mruby/mruby) | https://github.com/lihaochen910/raylib-mruby | | raylib-mruby | 2.5-dev | [mruby](https://github.com/mruby/mruby) | https://github.com/lihaochen910/raylib-mruby |
| pyraylib | 3.7 | [Python](https://www.python.org/) | https://github.com/Ho011/pyraylib |
| raylib-py | 2.0 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py | | raylib-py | 2.0 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py |
| raylib-python-cffi | 3.7 | [Python](https://www.python.org/) | https://github.com/electronstudio/raylib-python-cffi | | raylib-python-cffi | 3.7 | [Python](https://www.python.org/) | https://github.com/electronstudio/raylib-python-cffi |
| raylib-py-ctbg | 2.6 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py-ctbg | | raylib-py-ctbg | 2.6 | [Python](https://www.python.org/) | https://github.com/overdev/raylib-py-ctbg |
@ -82,6 +83,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
| jaylib | 3.0 | [Janet](https://janet-lang.org/) | https://github.com/janet-lang/jaylib | | jaylib | 3.0 | [Janet](https://janet-lang.org/) | https://github.com/janet-lang/jaylib |
| raykit | ? | [Kit](https://www.kitlang.org/) | https://github.com/Gamerfiend/raykit | | raykit | ? | [Kit](https://www.kitlang.org/) | https://github.com/Gamerfiend/raykit |
| vraylib | 3.5 | [V](https://vlang.io/) | https://github.com/waotzi/vraylib | | vraylib | 3.5 | [V](https://vlang.io/) | https://github.com/waotzi/vraylib |
| raylib.v | 3.7 | [V](https://vlang.io/) | https://github.com/irishgreencitrus/raylib.v |
| ray.mod | 3.0 | [BlitzMax](https://blitzmax.org/) | https://github.com/bmx-ng/ray.mod | | ray.mod | 3.0 | [BlitzMax](https://blitzmax.org/) | https://github.com/bmx-ng/ray.mod |
| raylib-ocaml | 3.7 | [OCaml](https://ocaml.org/) | https://github.com/tjammer/raylib-ocaml | | raylib-ocaml | 3.7 | [OCaml](https://ocaml.org/) | https://github.com/tjammer/raylib-ocaml |
| raylib-mosaic | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) | https://github.com/pluckyporcupine/raylib-mosaic | | raylib-mosaic | 3.0 | [Mosaic](https://github.com/sal55/langs/tree/master/Mosaic) | https://github.com/pluckyporcupine/raylib-mosaic |

View File

@ -43,7 +43,7 @@ int main(void)
// Render texture initialization, used to hold the rendering result so we can easily resize it // Render texture initialization, used to hold the rendering result so we can easily resize it
RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight); RenderTexture2D target = LoadRenderTexture(gameScreenWidth, gameScreenHeight);
SetTextureFilter(target.texture, FILTER_BILINEAR); // Texture scale filter to use SetTextureFilter(target.texture, TEXTURE_FILTER_BILINEAR); // Texture scale filter to use
Color colors[10] = { 0 }; Color colors[10] = { 0 };
for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 }; for (int i = 0; i < 10; i++) colors[i] = (Color){ GetRandomValue(100, 250), GetRandomValue(50, 150), GetRandomValue(10, 100), 255 };

View File

@ -41,7 +41,7 @@ int main(void)
Model model = LoadModel("resources/guy/guy.iqm"); // Load the animated model mesh and basic data Model model = LoadModel("resources/guy/guy.iqm"); // Load the animated model mesh and basic data
Texture2D texture = LoadTexture("resources/guy/guytex.png"); // Load model texture and set material Texture2D texture = LoadTexture("resources/guy/guytex.png"); // Load model texture and set material
SetMaterialTexture(&model.materials[0], MAP_DIFFUSE, texture); // Set model material map texture SetMaterialTexture(&model.materials[0], MATERIAL_MAP_DIFFUSE, texture); // Set model material map texture
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position

View File

@ -162,11 +162,11 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
mat.maps[MATERIAL_MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png"); mat.maps[MATERIAL_MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png");
// Set textures filtering for better quality // Set textures filtering for better quality
SetTextureFilter(mat.maps[MATERIAL_MAP_ALBEDO].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MATERIAL_MAP_ALBEDO].texture, TEXTURE_FILTER_BILINEAR);
SetTextureFilter(mat.maps[MATERIAL_MAP_NORMAL].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MATERIAL_MAP_NORMAL].texture, TEXTURE_FILTER_BILINEAR);
SetTextureFilter(mat.maps[MATERIAL_MAP_METALNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MATERIAL_MAP_METALNESS].texture, TEXTURE_FILTER_BILINEAR);
SetTextureFilter(mat.maps[MATERIAL_MAP_ROUGHNESS].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MATERIAL_MAP_ROUGHNESS].texture, TEXTURE_FILTER_BILINEAR);
SetTextureFilter(mat.maps[MATERIAL_MAP_OCCLUSION].texture, FILTER_BILINEAR); SetTextureFilter(mat.maps[MATERIAL_MAP_OCCLUSION].texture, TEXTURE_FILTER_BILINEAR);
// Enable sample usage in shader for assigned textures // Enable sample usage in shader for assigned textures
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, SHADER_UNIFORM_INT); SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, SHADER_UNIFORM_INT);

View File

@ -31,7 +31,7 @@ int main(void)
// Same as: Wave wave = LoadWave("sound.wav"); // Same as: Wave wave = LoadWave("sound.wav");
Wave wave = { Wave wave = {
.data = AUDIO_DATA, .data = AUDIO_DATA,
.sampleCount = AUDIO_SAMPLE_COUNT, .frameCount = AUDIO_FRAME_COUNT,
.sampleRate = AUDIO_SAMPLE_RATE, .sampleRate = AUDIO_SAMPLE_RATE,
.sampleSize = AUDIO_SAMPLE_SIZE, .sampleSize = AUDIO_SAMPLE_SIZE,
.channels = AUDIO_CHANNELS .channels = AUDIO_CHANNELS

View File

@ -11,7 +11,7 @@
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// Wave data information // Wave data information
#define AUDIO_SAMPLE_COUNT 24367 #define AUDIO_FRAME_COUNT 24367
#define AUDIO_SAMPLE_RATE 44100 #define AUDIO_SAMPLE_RATE 44100
#define AUDIO_SAMPLE_SIZE 32 #define AUDIO_SAMPLE_SIZE 32
#define AUDIO_CHANNELS 1 #define AUDIO_CHANNELS 1

View File

@ -31,11 +31,11 @@ int main(void)
const int screenWidth = 800; const int screenWidth = 800;
const int screenHeight = 450; const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Apply an shdrOutline to a texture"); InitWindow(screenWidth, screenHeight, "raylib [shaders] example - Apply an outline to a texture");
Texture2D egg = LoadTexture("resources/egg.png"); Texture2D egg = LoadTexture("resources/egg.png");
Texture2D torus = LoadTexture("resources/torus.png"); Texture2D torus = LoadTexture("resources/torus.png");
Shader shdrOutline = LoadShader(0, TextFormat("resources/shaders/glsl%i/shdrOutline.fs", GLSL_VERSION)); Shader shdrOutline = LoadShader(0, TextFormat("resources/shaders/glsl%i/outline.fs", GLSL_VERSION));
float outlineScale = 16.0f; float outlineScale = 16.0f;
float textureScale[2] = { 16.0f*4, 16.0f*4 }; float textureScale[2] = { 16.0f*4, 16.0f*4 };
@ -63,7 +63,7 @@ int main(void)
DrawTextureEx(torus, (Vector2){ 544, 230 }, 0.0, outlineScale, WHITE); DrawTextureEx(torus, (Vector2){ 544, 230 }, 0.0, outlineScale, WHITE);
EndShaderMode(); EndShaderMode();
DrawText("Shader-based shdrOutlines for textures", 190, 200, 20, LIGHTGRAY); DrawText("Shader-based outlines for textures", 190, 200, 20, LIGHTGRAY);
DrawFPS(710, 10); DrawFPS(710, 10);

View File

@ -454,16 +454,16 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
// Character destination rectangle on screen // Character destination rectangle on screen
// NOTE: We consider charsPadding on drawing // NOTE: We consider charsPadding on drawing
position.x += (float)(font.chars[index].offsetX - font.charsPadding)/(float)font.baseSize*scale; position.x += (float)(font.glyphs[index].offsetX - font.glyphPadding)/(float)font.baseSize*scale;
position.z += (float)(font.chars[index].offsetY - font.charsPadding)/(float)font.baseSize*scale; position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding)/(float)font.baseSize*scale;
// Character source rectangle from font texture atlas // Character source rectangle from font texture atlas
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects // NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding, Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding }; font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
float width = (float)(font.recs[index].width + 2.0f*font.charsPadding)/(float)font.baseSize*scale; float width = (float)(font.recs[index].width + 2.0f*font.glyphPadding)/(float)font.baseSize*scale;
float height = (float)(font.recs[index].height + 2.0f*font.charsPadding)/(float)font.baseSize*scale; float height = (float)(font.recs[index].height + 2.0f*font.glyphPadding)/(float)font.baseSize*scale;
if (font.texture.id > 0) if (font.texture.id > 0)
{ {
@ -477,16 +477,11 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
const float tw = (srcRec.x+srcRec.width)/font.texture.width; const float tw = (srcRec.x+srcRec.width)/font.texture.width;
const float th = (srcRec.y+srcRec.height)/font.texture.height; const float th = (srcRec.y+srcRec.height)/font.texture.height;
if (SHOW_LETTER_BOUNDRY) if (SHOW_LETTER_BOUNDRY) DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
DrawCubeWiresV((Vector3){ position.x + width/2, position.y, position.z + height/2}, (Vector3){ width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
#if defined(RAYLIB_NEW_RLGL)
rlCheckRenderBatchLimit(4 + 4*backface); rlCheckRenderBatchLimit(4 + 4*backface);
rlSetTexture(font.texture.id); rlSetTexture(font.texture.id);
#else
if (rlCheckBufferLimit(4 + 4*backface)) rlglDraw();
rlEnableTexture(font.texture.id);
#endif
rlPushMatrix(); rlPushMatrix();
rlTranslatef(position.x, position.y, position.z); rlTranslatef(position.x, position.y, position.z);
@ -512,11 +507,7 @@ void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontS
rlEnd(); rlEnd();
rlPopMatrix(); rlPopMatrix();
#if defined(RAYLIB_NEW_RLGL)
rlSetTexture(0); rlSetTexture(0);
#else
rlDisableTexture();
#endif
} }
} }
@ -554,8 +545,8 @@ void DrawText3D(Font font, const char *text, Vector3 position, float fontSize, f
DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint); DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint);
} }
if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale; else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
} }
i += codepointByteCount; // Move text bytes counter to next codepoint i += codepointByteCount; // Move text bytes counter to next codepoint
@ -592,8 +583,8 @@ Vector3 MeasureText3D(Font font, const char* text, float fontSize, float fontSpa
if (letter != '\n') if (letter != '\n')
{ {
if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale; if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale; else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale;
} }
else else
{ {
@ -670,8 +661,8 @@ void DrawTextWave3D(Font font, const char *text, Vector3 position, float fontSiz
DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint); DrawTextCodepoint3D(font, codepoint, (Vector3){ pos.x + textOffsetX, pos.y, pos.z + textOffsetY }, fontSize, backface, tint);
} }
if (font.chars[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale; if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing)/(float)font.baseSize*scale;
else textOffsetX += (float)(font.chars[index].advanceX + fontSpacing)/(float)font.baseSize*scale; else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing)/(float)font.baseSize*scale;
} }
i += codepointByteCount; // Move text bytes counter to next codepoint i += codepointByteCount; // Move text bytes counter to next codepoint
@ -714,8 +705,8 @@ Vector3 MeasureTextWave3D(Font font, const char* text, float fontSize, float fon
} }
else else
{ {
if (font.chars[index].advanceX != 0) textWidth += (font.chars[index].advanceX+fontSpacing)/(float)font.baseSize*scale; if (font.glyphs[index].advanceX != 0) textWidth += (font.glyphs[index].advanceX+fontSpacing)/(float)font.baseSize*scale;
else textWidth += (font.recs[index].width + font.chars[index].offsetX)/(float)font.baseSize*scale; else textWidth += (font.recs[index].width + font.glyphs[index].offsetX)/(float)font.baseSize*scale;
} }
} }
else else

View File

@ -39,24 +39,24 @@ int main(void)
// Default font generation from TTF font // Default font generation from TTF font
Font fontDefault = { 0 }; Font fontDefault = { 0 };
fontDefault.baseSize = 16; fontDefault.baseSize = 16;
fontDefault.charsCount = 95; fontDefault.glyphCount = 95;
// Loading font data from memory data // Loading font data from memory data
// Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array) // Parameters > font size: 16, no glyphs array provided (0), glyphs count: 95 (autogenerate chars array)
fontDefault.chars = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT); fontDefault.glyphs = LoadFontData(fileData, fileSize, 16, 0, 95, FONT_DEFAULT);
// Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default) // Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 4 px, pack method: 0 (default)
Image atlas = GenImageFontAtlas(fontDefault.chars, &fontDefault.recs, 95, 16, 4, 0); Image atlas = GenImageFontAtlas(fontDefault.glyphs, &fontDefault.recs, 95, 16, 4, 0);
fontDefault.texture = LoadTextureFromImage(atlas); fontDefault.texture = LoadTextureFromImage(atlas);
UnloadImage(atlas); UnloadImage(atlas);
// SDF font generation from TTF font // SDF font generation from TTF font
Font fontSDF = { 0 }; Font fontSDF = { 0 };
fontSDF.baseSize = 16; fontSDF.baseSize = 16;
fontSDF.charsCount = 95; fontSDF.glyphCount = 95;
// Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95) // Parameters > font size: 16, no glyphs array provided (0), glyphs count: 0 (defaults to 95)
fontSDF.chars = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF); fontSDF.glyphs = LoadFontData(fileData, fileSize, 16, 0, 0, FONT_SDF);
// Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm) // Parameters > glyphs count: 95, font size: 16, glyphs padding in image: 0 px, pack method: 1 (Skyline algorythm)
atlas = GenImageFontAtlas(fontSDF.chars, &fontSDF.recs, 95, 16, 0, 1); atlas = GenImageFontAtlas(fontSDF.glyphs, &fontSDF.recs, 95, 16, 0, 1);
fontSDF.texture = LoadTextureFromImage(atlas); fontSDF.texture = LoadTextureFromImage(atlas);
UnloadImage(atlas); UnloadImage(atlas);
@ -64,7 +64,7 @@ int main(void)
// Load SDF required shader (we use default vertex shader) // Load SDF required shader (we use default vertex shader)
Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/sdf.fs", GLSL_VERSION)); Shader shader = LoadShader(0, TextFormat("resources/shaders/glsl%i/sdf.fs", GLSL_VERSION));
SetTextureFilter(fontSDF.texture, FILTER_BILINEAR); // Required for SDF font SetTextureFilter(fontSDF.texture, TEXTURE_FILTER_BILINEAR); // Required for SDF font
Vector2 fontPosition = { 40, screenHeight/2.0f - 50 }; Vector2 fontPosition = { 40, screenHeight/2.0f - 50 };
Vector2 textSize = { 0.0f, 0.0f }; Vector2 textSize = { 0.0f, 0.0f };

View File

@ -13,8 +13,8 @@
#include "raylib.h" #include "raylib.h"
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection
// Main entry point // Main entry point
int main(void) int main(void)
@ -95,9 +95,7 @@ tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet ris
DrawRectangleLinesEx(container, 3, borderColor); // Draw container border DrawRectangleLinesEx(container, 3, borderColor); // Draw container border
// Draw text in container (add some padding) // Draw text in container (add some padding)
DrawTextRec(font, text, DrawTextBoxed(font, text, (Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 }, 20.0f, 2.0f, wordWrap, GRAY);
(Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 },
20.0f, 2.0f, wordWrap, GRAY);
DrawRectangleRec(resizer, borderColor); // Draw the resize box DrawRectangleRec(resizer, borderColor); // Draw the resize box
@ -130,13 +128,13 @@ tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet ris
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Draw text using font inside rectangle limits // Draw text using font inside rectangle limits
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
{ {
DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);
} }
// Draw text using font inside rectangle limits with support for text selection // Draw text using font inside rectangle limits with support for text selection
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint)
{ {
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
@ -168,7 +166,7 @@ static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float font
float glyphWidth = 0; float glyphWidth = 0;
if (codepoint != '\n') if (codepoint != '\n')
{ {
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor;
if (i + 1 < length) glyphWidth = glyphWidth + spacing; if (i + 1 < length) glyphWidth = glyphWidth + spacing;
} }

View File

@ -133,8 +133,8 @@ struct {
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
static void RandomizeEmoji(void); // Fills the emoji array with random emojis static void RandomizeEmoji(void); // Fills the emoji array with random emojis
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Global variables // Global variables
@ -273,12 +273,12 @@ int main(int argc, char **argv)
// Draw the main text message // Draw the main text message
Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height }; Rectangle textRect = { msgRect.x + horizontalPadding/2, msgRect.y + verticalPadding/2, msgRect.width - horizontalPadding, msgRect.height };
DrawTextRec(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE); DrawTextBoxed(*font, messages[message].text, textRect, (float)font->baseSize, 1.0f, true, WHITE);
// Draw the info text below the main message // Draw the info text below the main message
int size = (int)strlen(messages[message].text); int size = (int)strlen(messages[message].text);
int len = GetCodepointsCount(messages[message].text); int length = GetCodepointCount(messages[message].text);
const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, len, size); const char *info = TextFormat("%s %u characters %i bytes", messages[message].language, length, size);
sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f); sz = MeasureTextEx(GetFontDefault(), info, 10, 1.0f);
Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 }; Vector2 pos = { textRect.x + textRect.width - sz.x, msgRect.y + msgRect.height - sz.y - 2 };
DrawText(info, (int)pos.x, (int)pos.y, 10, RAYWHITE); DrawText(info, (int)pos.x, (int)pos.y, 10, RAYWHITE);
@ -329,13 +329,13 @@ static void RandomizeEmoji(void)
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Draw text using font inside rectangle limits // Draw text using font inside rectangle limits
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
{ {
DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);
} }
// Draw text using font inside rectangle limits with support for text selection // Draw text using font inside rectangle limits with support for text selection
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint)
{ {
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
@ -367,7 +367,7 @@ static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float font
float glyphWidth = 0; float glyphWidth = 0;
if (codepoint != '\n') if (codepoint != '\n')
{ {
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor; glyphWidth = (font.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[index].advanceX*scaleFactor;
if (i + 1 < length) glyphWidth = glyphWidth + spacing; if (i + 1 < length) glyphWidth = glyphWidth + spacing;
} }

View File

@ -26,8 +26,8 @@ int main(void)
Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM) Image image = LoadImage("resources/raylib_logo.png"); // Loaded in CPU memory (RAM)
Texture2D texture = LoadTextureFromImage(image); // Image converted to texture, GPU memory (VRAM) 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 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 SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------

View File

@ -2505,7 +2505,7 @@ Function 308: GetColor() (1 input parameters)
Name: GetColor Name: GetColor
Return type: Color Return type: Color
Description: Get Color structure from hexadecimal value Description: Get Color structure from hexadecimal value
Param[1]: hexValue (type: int) Param[1]: hexValue (type: unsigned int)
Function 309: GetPixelColor() (2 input parameters) Function 309: GetPixelColor() (2 input parameters)
Name: GetPixelColor Name: GetPixelColor
Return type: Color Return type: Color

View File

@ -389,7 +389,7 @@ RLAPI Vector3 ColorToHSV(Color color); // R
RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Returns a Color from HSV values RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Returns a Color from HSV values
RLAPI Color ColorAlpha(Color color, float alpha); // Returns color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Returns color with alpha applied, alpha goes from 0.0f to 1.0f
RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Returns src alpha-blended into dst color with tint RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Returns src alpha-blended into dst color with tint
RLAPI Color GetColor(int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format

View File

@ -385,7 +385,7 @@ typedef struct CoreData {
Matrix screenScale; // Matrix to scale screen (framebuffer rendering) Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
char **dropFilesPath; // Store dropped files paths as strings char **dropFilesPath; // Store dropped files paths as strings
int dropFilesCount; // Count dropped files strings int dropFileCount; // Count dropped files strings
} Window; } Window;
#if defined(PLATFORM_ANDROID) #if defined(PLATFORM_ANDROID)
@ -411,7 +411,7 @@ typedef struct CoreData {
int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue int keyPressedQueue[MAX_KEY_PRESSED_QUEUE]; // Input keys queue
int keyPressedQueueCount; // Input keys queue count int keyPressedQueueCount; // Input keys queue count
int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue int charPressedQueue[MAX_CHAR_PRESSED_QUEUE]; // Input characters queue (unicode)
int charPressedQueueCount; // Input characters queue count int charPressedQueueCount; // Input characters queue count
#if defined(PLATFORM_RPI) || defined(PLATFORM_DRM) #if defined(PLATFORM_RPI) || defined(PLATFORM_DRM)
@ -481,14 +481,14 @@ typedef struct CoreData {
static CoreData CORE = { 0 }; // Global CORE state context static CoreData CORE = { 0 }; // Global CORE state context
static char **dirFilesPath = NULL; // Store directory files paths as strings static char **dirFilesPath = NULL; // Store directory files paths as strings
static int dirFilesCount = 0; // Count directory files strings static int dirFileCount = 0; // Count directory files strings
#if defined(SUPPORT_SCREEN_CAPTURE) #if defined(SUPPORT_SCREEN_CAPTURE)
static int screenshotCounter = 0; // Screenshots counter static int screenshotCounter = 0; // Screenshots counter
#endif #endif
#if defined(SUPPORT_GIF_RECORDING) #if defined(SUPPORT_GIF_RECORDING)
static int gifFramesCounter = 0; // GIF frames counter static int gifFrameCounter = 0; // GIF frames counter
static bool gifRecording = false; // GIF recording state static bool gifRecording = false; // GIF recording state
static MsfGifState gifState = { 0 }; // MSGIF context state static MsfGifState gifState = { 0 }; // MSGIF context state
#endif #endif
@ -1926,10 +1926,10 @@ void EndDrawing(void)
if (gifRecording) if (gifRecording)
{ {
#define GIF_RECORD_FRAMERATE 10 #define GIF_RECORD_FRAMERATE 10
gifFramesCounter++; gifFrameCounter++;
// NOTE: We record one gif frame every 10 game frames // NOTE: We record one gif frame every 10 game frames
if ((gifFramesCounter%GIF_RECORD_FRAMERATE) == 0) if ((gifFrameCounter%GIF_RECORD_FRAMERATE) == 0)
{ {
// Get image data for the current frame (from backbuffer) // Get image data for the current frame (from backbuffer)
// NOTE: This process is quite slow... :( // NOTE: This process is quite slow... :(
@ -1939,7 +1939,7 @@ void EndDrawing(void)
RL_FREE(screenData); // Free image data RL_FREE(screenData); // Free image data
} }
if (((gifFramesCounter/15)%2) == 1) if (((gifFrameCounter/15)%2) == 1)
{ {
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON); DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED); DrawText("GIF RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
@ -1953,9 +1953,9 @@ void EndDrawing(void)
// Draw record/play indicator // Draw record/play indicator
if (eventsRecording) if (eventsRecording)
{ {
gifFramesCounter++; gifFrameCounter++;
if (((gifFramesCounter/15)%2) == 1) if (((gifFrameCounter/15)%2) == 1)
{ {
DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON); DrawCircle(30, CORE.Window.screen.height - 20, 10, MAROON);
DrawText("EVENTS RECORDING", 50, CORE.Window.screen.height - 25, 10, RED); DrawText("EVENTS RECORDING", 50, CORE.Window.screen.height - 25, 10, RED);
@ -1965,9 +1965,9 @@ void EndDrawing(void)
} }
else if (eventsPlaying) else if (eventsPlaying)
{ {
gifFramesCounter++; gifFrameCounter++;
if (((gifFramesCounter/15)%2) == 1) if (((gifFrameCounter/15)%2) == 1)
{ {
DrawCircle(30, CORE.Window.screen.height - 20, 10, LIME); DrawCircle(30, CORE.Window.screen.height - 20, 10, LIME);
DrawText("EVENTS PLAYING", 50, CORE.Window.screen.height - 25, 10, GREEN); DrawText("EVENTS PLAYING", 50, CORE.Window.screen.height - 25, 10, GREEN);
@ -2281,8 +2281,11 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
{ {
Shader shader = { 0 }; Shader shader = { 0 };
char *vShaderStr = LoadFileText(vsFileName); char *vShaderStr = NULL;
char *fShaderStr = LoadFileText(fsFileName); char *fShaderStr = NULL;
if (vsFileName != NULL) vShaderStr = LoadFileText(vsFileName);
if (fsFileName != NULL) fShaderStr = LoadFileText(fsFileName);
shader = LoadShaderFromMemory(vShaderStr, fShaderStr); shader = LoadShaderFromMemory(vShaderStr, fShaderStr);
@ -2764,9 +2767,9 @@ const char *GetFileNameWithoutExt(const char *filePath)
if (filePath != NULL) strcpy(fileName, GetFileName(filePath)); // Get filename with extension if (filePath != NULL) strcpy(fileName, GetFileName(filePath)); // Get filename with extension
int len = (int)strlen(fileName); int size = (int)strlen(fileName); // Get size in bytes
for (int i = 0; (i < len) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++) for (int i = 0; (i < size) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++)
{ {
if (fileName[i] == '.') if (fileName[i] == '.')
{ {
@ -2892,8 +2895,8 @@ char **GetDirectoryFiles(const char *dirPath, int *fileCount)
} }
else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file... else TRACELOG(LOG_WARNING, "FILEIO: Failed to open requested directory"); // Maybe it's a file...
dirFilesCount = counter; dirFileCount = counter;
*fileCount = dirFilesCount; *fileCount = dirFileCount;
return dirFilesPath; return dirFilesPath;
} }
@ -2901,14 +2904,14 @@ char **GetDirectoryFiles(const char *dirPath, int *fileCount)
// Clear directory files paths buffers // Clear directory files paths buffers
void ClearDirectoryFiles(void) void ClearDirectoryFiles(void)
{ {
if (dirFilesCount > 0) if (dirFileCount > 0)
{ {
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesPath[i]); for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesPath[i]);
RL_FREE(dirFilesPath); RL_FREE(dirFilesPath);
} }
dirFilesCount = 0; dirFileCount = 0;
} }
// Change working directory, returns true on success // Change working directory, returns true on success
@ -2924,27 +2927,27 @@ bool ChangeDirectory(const char *dir)
// Check if a file has been dropped into window // Check if a file has been dropped into window
bool IsFileDropped(void) bool IsFileDropped(void)
{ {
if (CORE.Window.dropFilesCount > 0) return true; if (CORE.Window.dropFileCount > 0) return true;
else return false; else return false;
} }
// Get dropped files names // Get dropped files names
char **GetDroppedFiles(int *count) char **GetDroppedFiles(int *count)
{ {
*count = CORE.Window.dropFilesCount; *count = CORE.Window.dropFileCount;
return CORE.Window.dropFilesPath; return CORE.Window.dropFilesPath;
} }
// Clear dropped files paths buffer // Clear dropped files paths buffer
void ClearDroppedFiles(void) void ClearDroppedFiles(void)
{ {
if (CORE.Window.dropFilesCount > 0) if (CORE.Window.dropFileCount > 0)
{ {
for (int i = 0; i < CORE.Window.dropFilesCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]); for (int i = 0; i < CORE.Window.dropFileCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]);
RL_FREE(CORE.Window.dropFilesPath); RL_FREE(CORE.Window.dropFilesPath);
CORE.Window.dropFilesCount = 0; CORE.Window.dropFileCount = 0;
} }
} }
@ -3580,6 +3583,17 @@ static bool InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSetErrorCallback(ErrorCallback); glfwSetErrorCallback(ErrorCallback);
/*
// Setup custom allocators to match raylib ones
const GLFWallocator allocator = {
.allocate = MemAlloc,
.deallocate = MemFree,
.reallocate = MemRealloc,
.user = NULL
};
glfwInitAllocator(&allocator);
*/
#if defined(__APPLE__) #if defined(__APPLE__)
glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE); glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_FALSE);
@ -4908,7 +4922,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
else else
{ {
gifRecording = true; gifRecording = true;
gifFramesCounter = 0; gifFrameCounter = 0;
msf_gif_begin(&gifState, CORE.Window.screen.width, CORE.Window.screen.height); msf_gif_begin(&gifState, CORE.Window.screen.width, CORE.Window.screen.height);
screenshotCounter++; screenshotCounter++;
@ -5045,7 +5059,8 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
// GLFW3 Srolling Callback, runs on mouse wheel // GLFW3 Srolling Callback, runs on mouse wheel
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset) static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
{ {
CORE.Input.Mouse.currentWheelMove = (float)yoffset; if (xoffset != 0.0) CORE.Input.Mouse.currentWheelMove = (float)xoffset;
else CORE.Input.Mouse.currentWheelMove = (float)yoffset;
} }
// GLFW3 CursorEnter Callback, when cursor enters the window // GLFW3 CursorEnter Callback, when cursor enters the window
@ -5070,7 +5085,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
strcpy(CORE.Window.dropFilesPath[i], paths[i]); strcpy(CORE.Window.dropFilesPath[i], paths[i]);
} }
CORE.Window.dropFilesCount = count; CORE.Window.dropFileCount = count;
} }
#endif #endif
@ -5130,7 +5145,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
/* /*
if (assetsReloadRequired) if (assetsReloadRequired)
{ {
for (int i = 0; i < assetsCount; i++) for (int i = 0; i < assetCount; i++)
{ {
// TODO: Unload old asset if required // TODO: Unload old asset if required

File diff suppressed because it is too large Load Diff

View File

@ -1,556 +0,0 @@
/**********************************************************************************************
*
* rIcons - Icons pack intended for tools development with raygui
*
* LICENSE: zlib/libpng
*
* Copyright (c) 2019-2020 Ramon Santamaria (@raysan5)
*
**********************************************************************************************/
#ifndef RICONS_H
#define RICONS_H
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define RICON_MAX_ICONS 256 // Maximum number of icons
#define RICON_SIZE 16 // Size of icons (squared)
#define RICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
// Icons data is defined by bit array (every bit represents one pixel)
// Those arrays are stored as unsigned int data arrays, so every array
// element defines 32 pixels (bits) of information
// Number of elemens depend on RICON_SIZE (by default 16x16 pixels)
#define RICON_DATA_ELEMENTS (RICON_SIZE*RICON_SIZE/32)
//----------------------------------------------------------------------------------
// Icons enumeration
//----------------------------------------------------------------------------------
typedef enum {
RICON_NONE = 0,
RICON_FOLDER_FILE_OPEN = 1,
RICON_FILE_SAVE_CLASSIC = 2,
RICON_FOLDER_OPEN = 3,
RICON_FOLDER_SAVE = 4,
RICON_FILE_OPEN = 5,
RICON_FILE_SAVE = 6,
RICON_FILE_EXPORT = 7,
RICON_FILE_NEW = 8,
RICON_FILE_DELETE = 9,
RICON_FILETYPE_TEXT = 10,
RICON_FILETYPE_AUDIO = 11,
RICON_FILETYPE_IMAGE = 12,
RICON_FILETYPE_PLAY = 13,
RICON_FILETYPE_VIDEO = 14,
RICON_FILETYPE_INFO = 15,
RICON_FILE_COPY = 16,
RICON_FILE_CUT = 17,
RICON_FILE_PASTE = 18,
RICON_CURSOR_HAND = 19,
RICON_CURSOR_POINTER = 20,
RICON_CURSOR_CLASSIC = 21,
RICON_PENCIL = 22,
RICON_PENCIL_BIG = 23,
RICON_BRUSH_CLASSIC = 24,
RICON_BRUSH_PAINTER = 25,
RICON_WATER_DROP = 26,
RICON_COLOR_PICKER = 27,
RICON_RUBBER = 28,
RICON_COLOR_BUCKET = 29,
RICON_TEXT_T = 30,
RICON_TEXT_A = 31,
RICON_SCALE = 32,
RICON_RESIZE = 33,
RICON_FILTER_POINT = 34,
RICON_FILTER_BILINEAR = 35,
RICON_CROP = 36,
RICON_CROP_ALPHA = 37,
RICON_SQUARE_TOGGLE = 38,
RICON_SYMMETRY = 39,
RICON_SYMMETRY_HORIZONTAL = 40,
RICON_SYMMETRY_VERTICAL = 41,
RICON_LENS = 42,
RICON_LENS_BIG = 43,
RICON_EYE_ON = 44,
RICON_EYE_OFF = 45,
RICON_FILTER_TOP = 46,
RICON_FILTER = 47,
RICON_TARGET_POINT = 48,
RICON_TARGET_SMALL = 49,
RICON_TARGET_BIG = 50,
RICON_TARGET_MOVE = 51,
RICON_CURSOR_MOVE = 52,
RICON_CURSOR_SCALE = 53,
RICON_CURSOR_SCALE_RIGHT = 54,
RICON_CURSOR_SCALE_LEFT = 55,
RICON_UNDO = 56,
RICON_REDO = 57,
RICON_REREDO = 58,
RICON_MUTATE = 59,
RICON_ROTATE = 60,
RICON_REPEAT = 61,
RICON_SHUFFLE = 62,
RICON_EMPTYBOX = 63,
RICON_TARGET = 64,
RICON_TARGET_SMALL_FILL = 65,
RICON_TARGET_BIG_FILL = 66,
RICON_TARGET_MOVE_FILL = 67,
RICON_CURSOR_MOVE_FILL = 68,
RICON_CURSOR_SCALE_FILL = 69,
RICON_CURSOR_SCALE_RIGHT_FILL = 70,
RICON_CURSOR_SCALE_LEFT_FILL = 71,
RICON_UNDO_FILL = 72,
RICON_REDO_FILL = 73,
RICON_REREDO_FILL = 74,
RICON_MUTATE_FILL = 75,
RICON_ROTATE_FILL = 76,
RICON_REPEAT_FILL = 77,
RICON_SHUFFLE_FILL = 78,
RICON_EMPTYBOX_SMALL = 79,
RICON_BOX = 80,
RICON_BOX_TOP = 81,
RICON_BOX_TOP_RIGHT = 82,
RICON_BOX_RIGHT = 83,
RICON_BOX_BOTTOM_RIGHT = 84,
RICON_BOX_BOTTOM = 85,
RICON_BOX_BOTTOM_LEFT = 86,
RICON_BOX_LEFT = 87,
RICON_BOX_TOP_LEFT = 88,
RICON_BOX_CENTER = 89,
RICON_BOX_CIRCLE_MASK = 90,
RICON_POT = 91,
RICON_ALPHA_MULTIPLY = 92,
RICON_ALPHA_CLEAR = 93,
RICON_DITHERING = 94,
RICON_MIPMAPS = 95,
RICON_BOX_GRID = 96,
RICON_GRID = 97,
RICON_BOX_CORNERS_SMALL = 98,
RICON_BOX_CORNERS_BIG = 99,
RICON_FOUR_BOXES = 100,
RICON_GRID_FILL = 101,
RICON_BOX_MULTISIZE = 102,
RICON_ZOOM_SMALL = 103,
RICON_ZOOM_MEDIUM = 104,
RICON_ZOOM_BIG = 105,
RICON_ZOOM_ALL = 106,
RICON_ZOOM_CENTER = 107,
RICON_BOX_DOTS_SMALL = 108,
RICON_BOX_DOTS_BIG = 109,
RICON_BOX_CONCENTRIC = 110,
RICON_BOX_GRID_BIG = 111,
RICON_OK_TICK = 112,
RICON_CROSS = 113,
RICON_ARROW_LEFT = 114,
RICON_ARROW_RIGHT = 115,
RICON_ARROW_BOTTOM = 116,
RICON_ARROW_TOP = 117,
RICON_ARROW_LEFT_FILL = 118,
RICON_ARROW_RIGHT_FILL = 119,
RICON_ARROW_BOTTOM_FILL = 120,
RICON_ARROW_TOP_FILL = 121,
RICON_AUDIO = 122,
RICON_FX = 123,
RICON_WAVE = 124,
RICON_WAVE_SINUS = 125,
RICON_WAVE_SQUARE = 126,
RICON_WAVE_TRIANGULAR = 127,
RICON_CROSS_SMALL = 128,
RICON_PLAYER_PREVIOUS = 129,
RICON_PLAYER_PLAY_BACK = 130,
RICON_PLAYER_PLAY = 131,
RICON_PLAYER_PAUSE = 132,
RICON_PLAYER_STOP = 133,
RICON_PLAYER_NEXT = 134,
RICON_PLAYER_RECORD = 135,
RICON_MAGNET = 136,
RICON_LOCK_CLOSE = 137,
RICON_LOCK_OPEN = 138,
RICON_CLOCK = 139,
RICON_TOOLS = 140,
RICON_GEAR = 141,
RICON_GEAR_BIG = 142,
RICON_BIN = 143,
RICON_HAND_POINTER = 144,
RICON_LASER = 145,
RICON_COIN = 146,
RICON_EXPLOSION = 147,
RICON_1UP = 148,
RICON_PLAYER = 149,
RICON_PLAYER_JUMP = 150,
RICON_KEY = 151,
RICON_DEMON = 152,
RICON_TEXT_POPUP = 153,
RICON_GEAR_EX = 154,
RICON_CRACK = 155,
RICON_CRACK_POINTS = 156,
RICON_STAR = 157,
RICON_DOOR = 158,
RICON_EXIT = 159,
RICON_MODE_2D = 160,
RICON_MODE_3D = 161,
RICON_CUBE = 162,
RICON_CUBE_FACE_TOP = 163,
RICON_CUBE_FACE_LEFT = 164,
RICON_CUBE_FACE_FRONT = 165,
RICON_CUBE_FACE_BOTTOM = 166,
RICON_CUBE_FACE_RIGHT = 167,
RICON_CUBE_FACE_BACK = 168,
RICON_CAMERA = 169,
RICON_SPECIAL = 170,
RICON_LINK_NET = 171,
RICON_LINK_BOXES = 172,
RICON_LINK_MULTI = 173,
RICON_LINK = 174,
RICON_LINK_BROKE = 175,
RICON_TEXT_NOTES = 176,
RICON_NOTEBOOK = 177,
RICON_SUITCASE = 178,
RICON_SUITCASE_ZIP = 179,
RICON_MAILBOX = 180,
RICON_MONITOR = 181,
RICON_PRINTER = 182,
RICON_PHOTO_CAMERA = 183,
RICON_PHOTO_CAMERA_FLASH = 184,
RICON_HOUSE = 185,
RICON_HEART = 186,
RICON_CORNER = 187,
RICON_VERTICAL_BARS = 188,
RICON_VERTICAL_BARS_FILL = 189,
RICON_LIFE_BARS = 190,
RICON_INFO = 191,
RICON_CROSSLINE = 192,
RICON_HELP = 193,
RICON_FILETYPE_ALPHA = 194,
RICON_FILETYPE_HOME = 195,
RICON_LAYERS_VISIBLE = 196,
RICON_LAYERS = 197,
RICON_WINDOW = 198,
RICON_HIDPI = 199,
RICON_200 = 200,
RICON_201 = 201,
RICON_202 = 202,
RICON_203 = 203,
RICON_204 = 204,
RICON_205 = 205,
RICON_206 = 206,
RICON_207 = 207,
RICON_208 = 208,
RICON_209 = 209,
RICON_210 = 210,
RICON_211 = 211,
RICON_212 = 212,
RICON_213 = 213,
RICON_214 = 214,
RICON_215 = 215,
RICON_216 = 216,
RICON_217 = 217,
RICON_218 = 218,
RICON_219 = 219,
RICON_220 = 220,
RICON_221 = 221,
RICON_222 = 222,
RICON_223 = 223,
RICON_224 = 224,
RICON_225 = 225,
RICON_226 = 226,
RICON_227 = 227,
RICON_228 = 228,
RICON_229 = 229,
RICON_230 = 230,
RICON_231 = 231,
RICON_232 = 232,
RICON_233 = 233,
RICON_234 = 234,
RICON_235 = 235,
RICON_236 = 236,
RICON_237 = 237,
RICON_238 = 238,
RICON_239 = 239,
RICON_240 = 240,
RICON_241 = 241,
RICON_242 = 242,
RICON_243 = 243,
RICON_244 = 244,
RICON_245 = 245,
RICON_246 = 246,
RICON_247 = 247,
RICON_248 = 248,
RICON_249 = 249,
RICON_250 = 250,
RICON_251 = 251,
RICON_252 = 252,
RICON_253 = 253,
RICON_254 = 254,
RICON_255 = 255,
} guiIconName;
#endif // RICONS_H
#if defined(RICONS_IMPLEMENTATION)
//----------------------------------------------------------------------------------
// Icons data (allocated on memory data section by default)
// NOTE: A new icon set could be loaded over this array using GuiLoadIcons(),
// just note that loaded icons set must be same RICON_SIZE
//----------------------------------------------------------------------------------
static unsigned int guiIcons[RICON_MAX_ICONS*RICON_DATA_ELEMENTS] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_NONE
0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // RICON_FOLDER_FILE_OPEN
0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // RICON_FILE_SAVE_CLASSIC
0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // RICON_FOLDER_OPEN
0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // RICON_FOLDER_SAVE
0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // RICON_FILE_OPEN
0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // RICON_FILE_SAVE
0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // RICON_FILE_EXPORT
0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // RICON_FILE_NEW
0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // RICON_FILE_DELETE
0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // RICON_FILETYPE_TEXT
0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // RICON_FILETYPE_AUDIO
0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // RICON_FILETYPE_IMAGE
0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // RICON_FILETYPE_PLAY
0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // RICON_FILETYPE_VIDEO
0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // RICON_FILETYPE_INFO
0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // RICON_FILE_COPY
0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // RICON_FILE_CUT
0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // RICON_FILE_PASTE
0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_CURSOR_HAND
0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // RICON_CURSOR_POINTER
0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // RICON_CURSOR_CLASSIC
0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // RICON_PENCIL
0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // RICON_PENCIL_BIG
0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // RICON_BRUSH_CLASSIC
0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // RICON_BRUSH_PAINTER
0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // RICON_WATER_DROP
0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // RICON_COLOR_PICKER
0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // RICON_RUBBER
0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // RICON_COLOR_BUCKET
0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // RICON_TEXT_T
0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // RICON_TEXT_A
0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // RICON_SCALE
0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // RICON_RESIZE
0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // RICON_FILTER_POINT
0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // RICON_FILTER_BILINEAR
0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // RICON_CROP
0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // RICON_CROP_ALPHA
0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // RICON_SQUARE_TOGGLE
0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // RICON_SIMMETRY
0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // RICON_SIMMETRY_HORIZONTAL
0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // RICON_SIMMETRY_VERTICAL
0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // RICON_LENS
0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // RICON_LENS_BIG
0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // RICON_EYE_ON
0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // RICON_EYE_OFF
0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // RICON_FILTER_TOP
0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // RICON_FILTER
0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // RICON_TARGET_POINT
0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // RICON_TARGET_SMALL
0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // RICON_TARGET_BIG
0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // RICON_TARGET_MOVE
0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // RICON_CURSOR_MOVE
0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // RICON_CURSOR_SCALE
0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // RICON_CURSOR_SCALE_RIGHT
0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // RICON_CURSOR_SCALE_LEFT
0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // RICON_UNDO
0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // RICON_REDO
0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // RICON_REREDO
0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // RICON_MUTATE
0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // RICON_ROTATE
0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // RICON_REPEAT
0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // RICON_SHUFFLE
0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // RICON_EMPTYBOX
0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // RICON_TARGET
0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // RICON_TARGET_SMALL_FILL
0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // RICON_TARGET_BIG_FILL
0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // RICON_TARGET_MOVE_FILL
0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // RICON_CURSOR_MOVE_FILL
0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // RICON_CURSOR_SCALE_FILL
0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // RICON_CURSOR_SCALE_RIGHT
0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // RICON_CURSOR_SCALE_LEFT
0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // RICON_UNDO_FILL
0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // RICON_REDO_FILL
0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // RICON_REREDO_FILL
0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // RICON_MUTATE_FILL
0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // RICON_ROTATE_FILL
0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // RICON_REPEAT_FILL
0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // RICON_SHUFFLE_FILL
0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // RICON_EMPTYBOX_SMALL
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX
0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_TOP
0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_TOP_RIGHT
0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_RIGHT
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // RICON_BOX_BOTTOM_RIGHT
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // RICON_BOX_BOTTOM
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // RICON_BOX_BOTTOM_LEFT
0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_LEFT
0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_TOP_LEFT
0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // RICON_BOX_CIRCLE_MASK
0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // RICON_BOX_CENTER
0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // RICON_POT
0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // RICON_ALPHA_MULTIPLY
0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // RICON_ALPHA_CLEAR
0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // RICON_DITHERING
0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // RICON_MIPMAPS
0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // RICON_BOX_GRID
0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // RICON_GRID
0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // RICON_BOX_CORNERS_SMALL
0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // RICON_BOX_CORNERS_BIG
0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // RICON_FOUR_BOXES
0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // RICON_GRID_FILL
0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // RICON_BOX_MULTISIZE
0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // RICON_ZOOM_SMALL
0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // RICON_ZOOM_MEDIUM
0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // RICON_ZOOM_BIG
0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // RICON_ZOOM_ALL
0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // RICON_ZOOM_CENTER
0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // RICON_BOX_DOTS_SMALL
0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // RICON_BOX_DOTS_BIG
0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // RICON_BOX_CONCENTRIC
0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // RICON_BOX_GRID_BIG
0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // RICON_OK_TICK
0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // RICON_CROSS
0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // RICON_ARROW_LEFT
0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // RICON_ARROW_RIGHT
0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // RICON_ARROW_BOTTOM
0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // RICON_ARROW_TOP
0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // RICON_ARROW_LEFT_FILL
0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // RICON_ARROW_RIGHT_FILL
0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // RICON_ARROW_BOTTOM_FILL
0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // RICON_ARROW_TOP_FILL
0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // RICON_AUDIO
0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // RICON_FX
0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // RICON_WAVE
0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // RICON_WAVE_SINUS
0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // RICON_WAVE_SQUARE
0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // RICON_WAVE_TRIANGULAR
0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // RICON_CROSS_SMALL
0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // RICON_PLAYER_PREVIOUS
0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // RICON_PLAYER_PLAY_BACK
0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // RICON_PLAYER_PLAY
0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // RICON_PLAYER_PAUSE
0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // RICON_PLAYER_STOP
0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // RICON_PLAYER_NEXT
0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // RICON_PLAYER_RECORD
0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // RICON_MAGNET
0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // RICON_LOCK_CLOSE
0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // RICON_LOCK_OPEN
0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // RICON_CLOCK
0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // RICON_TOOLS
0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // RICON_GEAR
0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // RICON_GEAR_BIG
0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // RICON_BIN
0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // RICON_HAND_POINTER
0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // RICON_LASER
0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // RICON_COIN
0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // RICON_EXPLOSION
0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // RICON_1UP
0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // RICON_PLAYER
0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // RICON_PLAYER_JUMP
0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // RICON_KEY
0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // RICON_DEMON
0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // RICON_TEXT_POPUP
0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // RICON_GEAR_EX
0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // RICON_CRACK
0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // RICON_CRACK_POINTS
0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // RICON_STAR
0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // RICON_DOOR
0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // RICON_EXIT
0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // RICON_MODE_2D
0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // RICON_MODE_3D
0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // RICON_CUBE
0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // RICON_CUBE_FACE_TOP
0x7fe00000, 0x50386030, 0x47fe483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // RICON_CUBE_FACE_LEFT
0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // RICON_CUBE_FACE_FRONT
0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3ff27fe2, 0x0ffe1ffa, 0x000007fe, // RICON_CUBE_FACE_BOTTOM
0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // RICON_CUBE_FACE_RIGHT
0x7fe00000, 0x7fe87ff0, 0x7ffe7fe4, 0x7fe27fe2, 0x7fe27fe2, 0x24127fe2, 0x0c06140a, 0x000007fe, // RICON_CUBE_FACE_BACK
0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // RICON_CAMERA
0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // RICON_SPECIAL
0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // RICON_LINK_NET
0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // RICON_LINK_BOXES
0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // RICON_LINK_MULTI
0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // RICON_LINK
0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // RICON_LINK_BROKE
0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // RICON_TEXT_NOTES
0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // RICON_NOTEBOOK
0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // RICON_SUITCASE
0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // RICON_SUITCASE_ZIP
0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // RICON_MAILBOX
0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // RICON_MONITOR
0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // RICON_PRINTER
0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // RICON_PHOTO_CAMERA
0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // RICON_PHOTO_CAMERA_FLASH
0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // RICON_HOUSE
0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // RICON_HEART
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // RICON_CORNER
0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // RICON_VERTICAL_BARS
0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // RICON_VERTICAL_BARS_FILL
0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // RICON_LIFE_BARS
0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // RICON_INFO
0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // RICON_CROSSLINE
0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // RICON_HELP
0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // RICON_FILETYPE_ALPHA
0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // RICON_FILETYPE_HOME
0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS_VISIBLE
0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // RICON_LAYERS
0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // RICON_WINDOW
0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // RICON_HIDPI
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_200
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_201
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_202
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_203
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_204
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_205
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_206
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_207
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_208
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_209
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_210
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_211
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_212
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_213
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_214
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_215
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_216
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_217
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_218
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_219
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_220
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_221
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_222
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_223
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_224
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_225
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_226
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_227
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_228
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_229
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_230
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_231
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_232
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_233
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_234
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_235
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_236
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_237
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_238
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_239
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_240
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_241
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_242
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_243
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_244
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_245
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_246
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_247
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_248
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_249
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_250
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_251
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_252
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_253
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_254
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RICON_255
};
#endif // RICONS_IMPLEMENTATION

View File

@ -276,6 +276,10 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
mempool->arena.offs += iter->size; mempool->arena.offs += iter->size;
__RemoveMemNode(list, iter); __RemoveMemNode(list, iter);
iter = list->head; iter = list->head;
if (iter == NULL) {
list->head = node;
return;
}
} }
const uintptr_t inode = ( uintptr_t )node; const uintptr_t inode = ( uintptr_t )node;
const uintptr_t iiter = ( uintptr_t )iter; const uintptr_t iiter = ( uintptr_t )iter;
@ -292,6 +296,14 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
iter->size += node->size; iter->size += node->size;
return; return;
} }
else if (iter->next == NULL)
{
// we reached the end of the free list -> append the node
iter->next = node;
node->prev = iter;
list->len++;
return;
}
} }
else if (iter > node) else if (iter > node)
{ {
@ -325,7 +337,7 @@ static void __InsertMemNode(MemPool *const mempool, AllocList *const list, MemNo
} }
else else
{ {
__InsertMemNodeBefore(list, iter, node); __InsertMemNodeBefore(list, node, iter);
list->len++; list->len++;
return; return;
} }

View File

@ -118,7 +118,7 @@ void UpdateGestures(void); // Update gestures detec
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
bool IsGestureDetected(int gesture); // Check if a gesture have been detected bool IsGestureDetected(int gesture); // Check if a gesture have been detected
int GetGestureDetected(void); // Get latest detected gesture int GetGestureDetected(void); // Get latest detected gesture
int GetTouchPointsCount(void); // Get touch points count int GetTouchPointCount(void); // Get touch points count
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
Vector2 GetGestureDragVector(void); // Get gesture drag vector Vector2 GetGestureDragVector(void); // Get gesture drag vector
float GetGestureDragAngle(void); // Get gesture drag angle float GetGestureDragAngle(void); // Get gesture drag angle
@ -431,7 +431,7 @@ void UpdateGestures(void)
} }
// Get number of touch points // Get number of touch points
int GetTouchPointsCount(void) int GetTouchPointCount(void)
{ {
// NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called

View File

@ -130,13 +130,16 @@ static ModelAnimation *LoadIQMModelAnimations(const char *fileName, int *animCou
static Model LoadGLTF(const char *fileName); // Load GLTF mesh data static Model LoadGLTF(const char *fileName); // Load GLTF mesh data
static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCount); // Load GLTF animation data
static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data); static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_data *data);
static void LoadGLTFMesh(cgltf_data *data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName); static void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
static void LoadGLTFNode(cgltf_data *data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName); static void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName);
static void InitGLTFBones(Model *model, const cgltf_data *data); static void InitGLTFBones(Model *model, const cgltf_data *data);
static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex); static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex);
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount); static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount);
static bool ReadGLTFValue(cgltf_accessor* acc, unsigned int index, void *variable); static bool ReadGLTFValue(cgltf_accessor *acc, unsigned int index, void *variable);
static void *ReadGLTFValuesAs(cgltf_accessor* acc, cgltf_component_type type, bool adjustOnDownCasting); static void *ReadGLTFValuesAs(cgltf_accessor *acc, cgltf_component_type type, bool adjustOnDownCasting);
#endif
#if defined(SUPPORT_FILEFORMAT_VOX)
static Model LoadVOX(const char* filename); //Load VOX mesh data
#endif #endif
#if defined(SUPPORT_FILEFORMAT_VOX) #if defined(SUPPORT_FILEFORMAT_VOX)
static Model LoadVOX(const char* filename); //Load VOX mesh data static Model LoadVOX(const char* filename); //Load VOX mesh data
@ -211,16 +214,16 @@ void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color)
} }
// Draw a triangle strip defined by points // Draw a triangle strip defined by points
void DrawTriangleStrip3D(Vector3 *points, int pointsCount, Color color) void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color)
{ {
if (pointsCount >= 3) if (pointCount >= 3)
{ {
rlCheckRenderBatchLimit(3*(pointsCount - 2)); rlCheckRenderBatchLimit(3*(pointCount - 2));
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 2; i < pointsCount; i++) for (int i = 2; i < pointCount; i++)
{ {
if ((i%2) == 0) if ((i%2) == 0)
{ {
@ -985,12 +988,6 @@ void UpdateMeshBuffer(Mesh mesh, int index, void *data, int dataSize, int offset
// Draw a 3d mesh with material and transform // Draw a 3d mesh with material and transform
void DrawMesh(Mesh mesh, Material material, Matrix transform) void DrawMesh(Mesh mesh, Material material, Matrix transform)
{
DrawMeshInstanced(mesh, material, &transform, 1);
}
// Draw multiple mesh instances with material and different transforms
void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances)
{ {
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
#define GL_VERTEX_ARRAY 0x8074 #define GL_VERTEX_ARRAY 0x8074
@ -1006,7 +1003,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors); rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
rlPushMatrix(); rlPushMatrix();
rlMultMatrixf(MatrixToFloat(transforms[0])); rlMultMatrixf(MatrixToFloat(transform));
rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r, rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r,
material.maps[MATERIAL_MAP_DIFFUSE].color.g, material.maps[MATERIAL_MAP_DIFFUSE].color.g,
material.maps[MATERIAL_MAP_DIFFUSE].color.b, material.maps[MATERIAL_MAP_DIFFUSE].color.b,
@ -1025,13 +1022,6 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Check instancing
bool instancing = false;
if (instances < 1) return;
else if (instances > 1) instancing = true;
float16 *instanceTransforms = NULL;
unsigned int instancesVboId = 0;
// Bind shader program // Bind shader program
rlEnableShader(material.shader.id); rlEnableShader(material.shader.id);
@ -1077,51 +1067,16 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView); if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection); if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
if (instancing)
{
// Create instances buffer
instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));
// Fill buffer with instances transformations as float16 arrays
for (int i = 0; i < instances; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);
// Enable mesh VAO to attach new buffer
rlEnableVertexArray(mesh.vaoId);
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData().
// It isn't clear which would be reliably faster in all cases and on all platforms,
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
// no faster, since we're transferring all the transform matrices anyway
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
// Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL
for (unsigned int i = 0; i < 4; i++)
{
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), (void *)(i*sizeof(Vector4)));
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1);
}
rlDisableVertexBuffer();
rlDisableVertexArray();
// Accumulate internal matrix transform (push/pop) and view matrix
// NOTE: In this case, model instance transformation must be computed in the shader
matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);
}
else
{
// Model transformation matrix is send to shader uniform location: SHADER_LOC_MATRIX_MODEL // Model transformation matrix is send to shader uniform location: SHADER_LOC_MATRIX_MODEL
if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transforms[0]); if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform);
// Accumulate several model transformations: // Accumulate several model transformations:
// transforms[0]: model transformation provided (includes DrawModel() params combined with model.transform) // transform: model transformation provided (includes DrawModel() params combined with model.transform)
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack // rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
matModel = MatrixMultiply(transforms[0], rlGetMatrixTransform()); matModel = MatrixMultiply(transform, rlGetMatrixTransform());
// Get model-view matrix // Get model-view matrix
matModelView = MatrixMultiply(matModel, matView); matModelView = MatrixMultiply(matModel, matView);
}
// Upload model normal matrix (if locations available) // Upload model normal matrix (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
@ -1205,14 +1160,14 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
} }
int eyesCount = 1; int eyeCount = 1;
if (rlIsStereoRenderEnabled()) eyesCount = 2; if (rlIsStereoRenderEnabled()) eyeCount = 2;
for (int eye = 0; eye < eyesCount; eye++) for (int eye = 0; eye < eyeCount; eye++)
{ {
// Calculate model-view-projection matrix (MVP) // Calculate model-view-projection matrix (MVP)
Matrix matModelViewProjection = MatrixIdentity(); Matrix matModelViewProjection = MatrixIdentity();
if (eyesCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection); if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
else else
{ {
// Setup current eye viewport (half screen width) // Setup current eye viewport (half screen width)
@ -1223,17 +1178,10 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
// Send combined model-view-projection matrix to shader // Send combined model-view-projection matrix to shader
rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection); rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);
if (instancing) // Draw mesh instanced // Draw mesh
{
if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);
else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);
}
else // Draw mesh
{
if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0); if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, 0);
else rlDrawVertexArray(0, mesh.vertexCount); else rlDrawVertexArray(0, mesh.vertexCount);
} }
}
// Unbind all binded texture maps // Unbind all binded texture maps
for (int i = 0; i < MAX_MATERIAL_MAPS; i++) for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
@ -1256,18 +1204,224 @@ void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int ins
// Disable shader program // Disable shader program
rlDisableShader(); rlDisableShader();
if (instancing)
{
// Remove instance transforms buffer
rlUnloadVertexBuffer(instancesVboId);
RL_FREE(instanceTransforms);
}
else
{
// Restore rlgl internal modelview and projection matrices // Restore rlgl internal modelview and projection matrices
rlSetMatrixModelview(matView); rlSetMatrixModelview(matView);
rlSetMatrixProjection(matProjection); rlSetMatrixProjection(matProjection);
#endif
}
// Draw multiple mesh instances with material and different transforms
void DrawMeshInstanced(Mesh mesh, Material material, Matrix *transforms, int instances)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Instancing required variables
float16 *instanceTransforms = NULL;
unsigned int instancesVboId = 0;
// Bind shader program
rlEnableShader(material.shader.id);
// Send required data to shader (matrices, values)
//-----------------------------------------------------
// Upload to shader material.colDiffuse
if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)
{
float values[4] = {
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f
};
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);
} }
// Upload to shader material.colSpecular (if location available)
if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1)
{
float values[4] = {
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f,
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.g/255.0f,
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.b/255.0f,
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f
};
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);
}
// Get a copy of current matrices to work with,
// just in case stereo render is required and we need to modify them
// NOTE: At this point the modelview matrix just contains the view matrix (camera)
// That's because BeginMode3D() sets it and there is no model-drawing function
// that modifies it, all use rlPushMatrix() and rlPopMatrix()
Matrix matModel = MatrixIdentity();
Matrix matView = rlGetMatrixModelview();
Matrix matModelView = MatrixIdentity();
Matrix matProjection = rlGetMatrixProjection();
// Upload view and projection matrices (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
// Create instances buffer
instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));
// Fill buffer with instances transformations as float16 arrays
for (int i = 0; i < instances; i++) instanceTransforms[i] = MatrixToFloatV(transforms[i]);
// Enable mesh VAO to attach new buffer
rlEnableVertexArray(mesh.vaoId);
// This could alternatively use a static VBO and either glMapBuffer() or glBufferSubData().
// It isn't clear which would be reliably faster in all cases and on all platforms,
// anecdotally glMapBuffer() seems very slow (syncs) while glBufferSubData() seems
// no faster, since we're transferring all the transform matrices anyway
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
// Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL
for (unsigned int i = 0; i < 4; i++)
{
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), (void *)(i*sizeof(Vector4)));
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1);
}
rlDisableVertexBuffer();
rlDisableVertexArray();
// Accumulate internal matrix transform (push/pop) and view matrix
// NOTE: In this case, model instance transformation must be computed in the shader
matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);
// Upload model normal matrix (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
//-----------------------------------------------------
// Bind active texture maps (if available)
for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
{
if (material.maps[i].texture.id > 0)
{
// Select current shader texture slot
rlActiveTextureSlot(i);
// Enable texture for active slot
if ((i == MATERIAL_MAP_IRRADIANCE) ||
(i == MATERIAL_MAP_PREFILTER) ||
(i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);
else rlEnableTexture(material.maps[i].texture.id);
rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);
}
}
// Try binding vertex array objects (VAO)
// or use VBOs if not possible
if (!rlEnableVertexArray(mesh.vaoId))
{
// Bind mesh VBO data: vertex position (shader-location = 0)
rlEnableVertexBuffer(mesh.vboId[0]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]);
// Bind mesh VBO data: vertex texcoords (shader-location = 1)
rlEnableVertexBuffer(mesh.vboId[1]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
{
// Bind mesh VBO data: vertex normals (shader-location = 2)
rlEnableVertexBuffer(mesh.vboId[2]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]);
}
// Bind mesh VBO data: vertex colors (shader-location = 3, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1)
{
if (mesh.vboId[3] != 0)
{
rlEnableVertexBuffer(mesh.vboId[3]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
}
else
{
// Set default value for unused attribute
// NOTE: Required when using default shader and no VAO support
float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC2, 4);
rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]);
}
}
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
{
rlEnableVertexBuffer(mesh.vboId[4]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]);
}
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
{
rlEnableVertexBuffer(mesh.vboId[5]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
}
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
}
int eyeCount = 1;
if (rlIsStereoRenderEnabled()) eyeCount = 2;
for (int eye = 0; eye < eyeCount; eye++)
{
// Calculate model-view-projection matrix (MVP)
Matrix matModelViewProjection = MatrixIdentity();
if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
else
{
// Setup current eye viewport (half screen width)
rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());
matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));
}
// Send combined model-view-projection matrix to shader
rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);
// Draw mesh instanced
if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);
else rlDrawVertexArrayInstanced(0, mesh.vertexCount, instances);
}
// Unbind all binded texture maps
for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
{
// Select current shader texture slot
rlActiveTextureSlot(i);
// Disable texture for active slot
if ((i == MATERIAL_MAP_IRRADIANCE) ||
(i == MATERIAL_MAP_PREFILTER) ||
(i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();
else rlDisableTexture();
}
// Disable all possible vertex array objects (or VBOs)
rlDisableVertexArray();
rlDisableVertexBuffer();
rlDisableVertexBufferElement();
// Disable shader program
rlDisableShader();
// Remove instance transforms buffer
rlUnloadVertexBuffer(instancesVboId);
RL_FREE(instanceTransforms);
#endif #endif
} }
@ -1310,43 +1464,43 @@ bool ExportMesh(Mesh mesh, const char *fileName)
// NOTE: Text data buffer size is estimated considering mesh data size // NOTE: Text data buffer size is estimated considering mesh data size
char *txtData = (char *)RL_CALLOC(dataSize + 2000, sizeof(char)); char *txtData = (char *)RL_CALLOC(dataSize + 2000, sizeof(char));
int bytesCount = 0; int byteCount = 0;
bytesCount += sprintf(txtData + bytesCount, "# //////////////////////////////////////////////////////////////////////////////////\n"); byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n");
bytesCount += sprintf(txtData + bytesCount, "# // //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n");
bytesCount += sprintf(txtData + bytesCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n"); byteCount += sprintf(txtData + byteCount, "# // rMeshOBJ exporter v1.0 - Mesh exported as triangle faces and not optimized //\n");
bytesCount += sprintf(txtData + bytesCount, "# // //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n");
bytesCount += sprintf(txtData + bytesCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n"); byteCount += sprintf(txtData + byteCount, "# // more info and bugs-report: github.com/raysan5/raylib //\n");
bytesCount += sprintf(txtData + bytesCount, "# // feedback and support: ray[at]raylib.com //\n"); byteCount += sprintf(txtData + byteCount, "# // feedback and support: ray[at]raylib.com //\n");
bytesCount += sprintf(txtData + bytesCount, "# // //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n");
bytesCount += sprintf(txtData + bytesCount, "# // Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n"); byteCount += sprintf(txtData + byteCount, "# // Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n");
bytesCount += sprintf(txtData + bytesCount, "# // //\n"); byteCount += sprintf(txtData + byteCount, "# // //\n");
bytesCount += sprintf(txtData + bytesCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n"); byteCount += sprintf(txtData + byteCount, "# //////////////////////////////////////////////////////////////////////////////////\n\n");
bytesCount += sprintf(txtData + bytesCount, "# Vertex Count: %i\n", mesh.vertexCount); byteCount += sprintf(txtData + byteCount, "# Vertex Count: %i\n", mesh.vertexCount);
bytesCount += sprintf(txtData + bytesCount, "# Triangle Count: %i\n\n", mesh.triangleCount); byteCount += sprintf(txtData + byteCount, "# Triangle Count: %i\n\n", mesh.triangleCount);
bytesCount += sprintf(txtData + bytesCount, "g mesh\n"); byteCount += sprintf(txtData + byteCount, "g mesh\n");
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3) for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
{ {
bytesCount += sprintf(txtData + bytesCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]); byteCount += sprintf(txtData + byteCount, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
} }
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2) for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
{ {
bytesCount += sprintf(txtData + bytesCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]); byteCount += sprintf(txtData + byteCount, "vt %.3f %.3f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
} }
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3) for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
{ {
bytesCount += sprintf(txtData + bytesCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]); byteCount += sprintf(txtData + byteCount, "vn %.3f %.3f %.3f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
} }
for (int i = 0; i < mesh.triangleCount; i += 3) for (int i = 0; i < mesh.triangleCount; i += 3)
{ {
bytesCount += sprintf(txtData + bytesCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2); byteCount += sprintf(txtData + byteCount, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2);
} }
bytesCount += sprintf(txtData + bytesCount, "\n"); byteCount += sprintf(txtData + byteCount, "\n");
// NOTE: Text data length exported is determined by '\0' (NULL) character // NOTE: Text data length exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData); success = SaveFileText(fileName, txtData);
@ -3353,6 +3507,11 @@ RayCollision GetRayCollisionQuad(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Ve
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if defined(SUPPORT_FILEFORMAT_OBJ) #if defined(SUPPORT_FILEFORMAT_OBJ)
// Load OBJ mesh data // Load OBJ mesh data
//
// Keep the following information in mind when reading this
// - A mesh is created for every material present in the obj file
// - the model.meshCount is therefore the materialCount returned from tinyobj
// - the mesh is automatically triangulated by tinyobj
static Model LoadOBJ(const char *fileName) static Model LoadOBJ(const char *fileName)
{ {
Model model = { 0 }; Model model = { 0 };
@ -3404,15 +3563,13 @@ static Model LoadOBJ(const char *fileName)
// Count the faces for each material // Count the faces for each material
int *matFaces = RL_CALLOC(materialCount, sizeof(int)); int *matFaces = RL_CALLOC(materialCount, sizeof(int));
for (unsigned int mi = 0; mi < meshCount; mi++) for (int fi = 0; fi< attrib.num_faces; fi++)
{ {
for (unsigned int fi = 0; fi < meshes[mi].length; fi++) tinyobj_vertex_index_t face = attrib.faces[fi];
{ int idx = attrib.material_ids[fi];
int idx = attrib.material_ids[meshes[mi].face_offset + fi];
if (idx == -1) idx = 0; // for no material face (which could be the whole model)
matFaces[idx]++; matFaces[idx]++;
} }
}
//-------------------------------------- //--------------------------------------
// Create the material meshes // Create the material meshes
@ -4718,14 +4875,14 @@ static Model LoadGLTF(const char *fileName)
if (data->scenes_count > 1) TRACELOG(LOG_INFO, "MODEL: [%s] Has multiple scenes but only the first one will be loaded", fileName); if (data->scenes_count > 1) TRACELOG(LOG_INFO, "MODEL: [%s] Has multiple scenes but only the first one will be loaded", fileName);
int primitivesCount = 0; int primitiveCount = 0;
for (unsigned int i = 0; i < data->scene->nodes_count; i++) for (unsigned int i = 0; i < data->scene->nodes_count; i++)
{ {
GetGLTFPrimitiveCount(data->scene->nodes[i], &primitivesCount); GetGLTFPrimitiveCount(data->scene->nodes[i], &primitiveCount);
} }
// Process glTF data and map to model // Process glTF data and map to model
model.meshCount = primitivesCount; model.meshCount = primitiveCount;
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh)); model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
model.materialCount = (int)data->materials_count + 1; model.materialCount = (int)data->materials_count + 1;
model.materials = RL_MALLOC(model.materialCount*sizeof(Material)); model.materials = RL_MALLOC(model.materialCount*sizeof(Material));
@ -4753,7 +4910,7 @@ static Model LoadGLTF(const char *fileName)
return model; return model;
} }
static void InitGLTFBones(Model* model, const cgltf_data* data) static void InitGLTFBones(Model *model, const cgltf_data *data)
{ {
for (unsigned int j = 0; j < data->nodes_count; j++) for (unsigned int j = 0; j < data->nodes_count; j++)
{ {
@ -4776,7 +4933,7 @@ static void InitGLTFBones(Model* model, const cgltf_data* data)
} }
{ {
bool* completedBones = RL_CALLOC(model->boneCount, sizeof(bool)); bool *completedBones = RL_CALLOC(model->boneCount, sizeof(bool));
int numberCompletedBones = 0; int numberCompletedBones = 0;
while (numberCompletedBones < model->boneCount) while (numberCompletedBones < model->boneCount)
@ -4884,7 +5041,7 @@ static void LoadGLTFMaterial(Model *model, const char *fileName, const cgltf_dat
model->materials[model->materialCount - 1] = LoadMaterialDefault(); model->materials[model->materialCount - 1] = LoadMaterialDefault();
} }
static void BindGLTFPrimitiveToBones(Model* model, const cgltf_data* data, int primitiveIndex) static void BindGLTFPrimitiveToBones(Model *model, const cgltf_data *data, int primitiveIndex)
{ {
for (unsigned int nodeId = 0; nodeId < data->nodes_count; nodeId++) for (unsigned int nodeId = 0; nodeId < data->nodes_count; nodeId++)
{ {
@ -4892,12 +5049,12 @@ static void BindGLTFPrimitiveToBones(Model* model, const cgltf_data* data, int p
{ {
if (model->meshes[primitiveIndex].boneIds == NULL) if (model->meshes[primitiveIndex].boneIds == NULL)
{ {
model->meshes[primitiveIndex].boneIds = RL_CALLOC(4*model->meshes[primitiveIndex].vertexCount, sizeof(int)); model->meshes[primitiveIndex].boneIds = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(int));
model->meshes[primitiveIndex].boneWeights = RL_CALLOC(4*model->meshes[primitiveIndex].vertexCount, sizeof(float)); model->meshes[primitiveIndex].boneWeights = RL_CALLOC(model->meshes[primitiveIndex].vertexCount*4, sizeof(float));
for (int b = 0; b < 4*model->meshes[primitiveIndex].vertexCount; b++) for (int b = 0; b < model->meshes[primitiveIndex].vertexCount*4; b++)
{ {
if (b % 4 == 0) if (b%4 == 0)
{ {
model->meshes[primitiveIndex].boneIds[b] = nodeId; model->meshes[primitiveIndex].boneIds[b] = nodeId;
model->meshes[primitiveIndex].boneWeights[b] = 1.0f; model->meshes[primitiveIndex].boneWeights[b] = 1.0f;
@ -4974,7 +5131,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
// Getting the max animation time to consider for animation duration // Getting the max animation time to consider for animation duration
for (unsigned int i = 0; i < animation->channels_count; i++) for (unsigned int i = 0; i < animation->channels_count; i++)
{ {
cgltf_animation_channel* channel = animation->channels + i; cgltf_animation_channel *channel = animation->channels + i;
int frameCounts = (int)channel->sampler->input->count; int frameCounts = (int)channel->sampler->input->count;
float lastFrameTime = 0.0f; float lastFrameTime = 0.0f;
@ -5021,8 +5178,8 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
// for each single transformation type on single bone // for each single transformation type on single bone
for (unsigned int channelId = 0; channelId < animation->channels_count; channelId++) for (unsigned int channelId = 0; channelId < animation->channels_count; channelId++)
{ {
cgltf_animation_channel* channel = animation->channels + channelId; cgltf_animation_channel *channel = animation->channels + channelId;
cgltf_animation_sampler* sampler = channel->sampler; cgltf_animation_sampler *sampler = channel->sampler;
int boneId = (int)(channel->target_node - data->nodes); int boneId = (int)(channel->target_node - data->nodes);
@ -5180,7 +5337,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
return animations; return animations;
} }
void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName) void LoadGLTFMesh(cgltf_data *data, cgltf_mesh *mesh, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName)
{ {
for (unsigned int p = 0; p < mesh->primitives_count; p++) for (unsigned int p = 0; p < mesh->primitives_count; p++)
{ {
@ -5305,7 +5462,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu
} }
} }
void LoadGLTFNode(cgltf_data* data, cgltf_node* node, Model* outModel, Matrix currentTransform, int* primitiveIndex, const char *fileName) void LoadGLTFNode(cgltf_data *data, cgltf_node *node, Model *outModel, Matrix currentTransform, int *primitiveIndex, const char *fileName)
{ {
Matrix nodeTransform = { Matrix nodeTransform = {
node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12], node->matrix[0], node->matrix[4], node->matrix[8], node->matrix[12],
@ -5320,7 +5477,7 @@ void LoadGLTFNode(cgltf_data* data, cgltf_node* node, Model* outModel, Matrix cu
for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName); for (unsigned int i = 0; i < node->children_count; i++) LoadGLTFNode(data, node->children[i], outModel, currentTransform, primitiveIndex, fileName);
} }
static void GetGLTFPrimitiveCount(cgltf_node* node, int* outCount) static void GetGLTFPrimitiveCount(cgltf_node *node, int *outCount)
{ {
if (node->mesh != NULL) *outCount += node->mesh->primitives_count; if (node->mesh != NULL) *outCount += node->mesh->primitives_count;

View File

@ -877,14 +877,14 @@ void UnloadSound(Sound sound)
} }
// Update sound buffer with new data // Update sound buffer with new data
void UpdateSound(Sound sound, const void *data, int samplesCount) void UpdateSound(Sound sound, const void *data, int sampleCount)
{ {
if (sound.stream.buffer != NULL) if (sound.stream.buffer != NULL)
{ {
StopAudioBuffer(sound.stream.buffer); StopAudioBuffer(sound.stream.buffer);
// TODO: May want to lock/unlock this since this data buffer is read at mixing time // TODO: May want to lock/unlock this since this data buffer is read at mixing time
memcpy(sound.stream.buffer->data, data, samplesCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.config.formatIn, sound.stream.buffer->converter.config.channelsIn)); memcpy(sound.stream.buffer->data, data, sampleCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.config.formatIn, sound.stream.buffer->converter.config.channelsIn));
} }
} }
@ -942,19 +942,19 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
// NOTE: Text data buffer size is estimated considering wave data size in bytes // NOTE: Text data buffer size is estimated considering wave data size in bytes
// and requiring 6 char bytes for every byte: "0x00, " // and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(6*waveDataSize + 2000, sizeof(char)); char *txtData = (char *)RL_CALLOC(waveDataSize*6 + 2000, sizeof(char));
int bytesCount = 0; int byteCount = 0;
bytesCount += sprintf(txtData + bytesCount, "\n//////////////////////////////////////////////////////////////////////////////////\n"); byteCount += sprintf(txtData + byteCount, "\n//////////////////////////////////////////////////////////////////////////////////\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// WaveAsCode exporter v1.0 - Wave data exported as an array of bytes //\n"); byteCount += sprintf(txtData + byteCount, "// WaveAsCode exporter v1.0 - Wave data exported as an array of bytes //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// more info and bugs-report: github.com/raysan5/raylib //\n"); byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
bytesCount += sprintf(txtData + bytesCount, "// feedback and support: ray[at]raylib.com //\n"); byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// Copyright (c) 2018 Ramon Santamaria (@raysan5) //\n"); byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "//////////////////////////////////////////////////////////////////////////////////\n\n"); byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
char varFileName[256] = { 0 }; char varFileName[256] = { 0 };
#if !defined(RAUDIO_STANDALONE) #if !defined(RAUDIO_STANDALONE)
@ -965,17 +965,18 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
strcpy(varFileName, fileName); strcpy(varFileName, fileName);
#endif #endif
bytesCount += sprintf(txtData + bytesCount, "// Wave data information\n"); byteCount += sprintf(txtData + byteCount, "// Wave data information\n");
bytesCount += sprintf(txtData + bytesCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount); byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_COUNT %u\n", varFileName, wave.frameCount*wave.channels); byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate); byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
bytesCount += sprintf(txtData + bytesCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize); byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
bytesCount += sprintf(txtData + bytesCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels); byteCount += sprintf(txtData + byteCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
// Write byte data as hexadecimal text // Write byte data as hexadecimal text
bytesCount += sprintf(txtData + bytesCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize); // NOTE: Frame data exported is interlaced: Frame01[Sample-Channel01, Sample-Channel02, ...], Frame02[], Frame03[]
for (int i = 0; i < waveDataSize - 1; i++) bytesCount += sprintf(txtData + bytesCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]); byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize);
bytesCount += sprintf(txtData + bytesCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]); for (int i = 0; i < waveDataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)wave.data)[i]);
byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
// NOTE: Text data length exported is determined by '\0' (NULL) character // NOTE: Text data length exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData); success = SaveFileText(fileName, txtData);
@ -1504,9 +1505,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, unsigned char *data, int d
// Copy data to allocated memory for default UnloadMusicStream // Copy data to allocated memory for default UnloadMusicStream
unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize); unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
int it = dataSize/sizeof(unsigned char); int it = dataSize/sizeof(unsigned char);
for (int i = 0; i < it; i++){ for (int i = 0; i < it; i++) newData[i] = data[i];
newData[i] = data[i];
}
// Memory loaded version for jar_mod_load_file() // Memory loaded version for jar_mod_load_file()
if (dataSize && dataSize < 32*1024*1024) if (dataSize && dataSize < 32*1024*1024)
@ -1715,7 +1714,7 @@ void UpdateMusicStream(Music music)
#if defined(SUPPORT_FILEFORMAT_XM) #if defined(SUPPORT_FILEFORMAT_XM)
case MUSIC_MODULE_XM: case MUSIC_MODULE_XM:
{ {
// NOTE: Internally we consider 2 channels generation, so samplesCount/2 // NOTE: Internally we consider 2 channels generation, so sampleCount/2
if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream); if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)pcm, frameCountToStream);
else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream); else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)pcm, frameCountToStream);
else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream); else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)pcm, frameCountToStream);

View File

@ -134,6 +134,8 @@
// Other modules (raymath, rlgl) also require some of those types, so, // Other modules (raymath, rlgl) also require some of those types, so,
// to be able to use those other modules as standalone (not depending on raylib) // to be able to use those other modules as standalone (not depending on raylib)
// this defines are very useful for internal check and avoid type (re)definitions // this defines are very useful for internal check and avoid type (re)definitions
#define RL_COLOR_TYPE
#define RL_RECTANGLE_TYPE
#define RL_VECTOR2_TYPE #define RL_VECTOR2_TYPE
#define RL_VECTOR3_TYPE #define RL_VECTOR3_TYPE
#define RL_VECTOR4_TYPE #define RL_VECTOR4_TYPE
@ -170,14 +172,6 @@
#define MAGENTA CLITERAL(Color){ 255, 0, 255, 255 } // Magenta #define MAGENTA CLITERAL(Color){ 255, 0, 255, 255 } // Magenta
#define RAYWHITE CLITERAL(Color){ 245, 245, 245, 255 } // My own White (raylib logo) #define RAYWHITE CLITERAL(Color){ 245, 245, 245, 255 } // My own White (raylib logo)
// WARNING: Temporal hacks to avoid breaking old codebases using
// deprecated raylib implementations or definitions
#define GetImageData LoadImageColors
#define FILTER_POINT TEXTURE_FILTER_POINT
#define FILTER_BILINEAR TEXTURE_FILTER_BILINEAR
#define MAP_DIFFUSE MATERIAL_MAP_DIFFUSE
#define UNCOMPRESSED_R8G8B8A8 PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Structures Definition // Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -293,11 +287,11 @@ typedef struct GlyphInfo {
// Font, font texture and GlyphInfo array data // Font, font texture and GlyphInfo array data
typedef struct Font { typedef struct Font {
int baseSize; // Base size (default chars height) int baseSize; // Base size (default chars height)
int charsCount; // Number of characters int glyphCount; // Number of glyph characters
int charsPadding; // Padding around the chars int glyphPadding; // Padding around the glyph characters
Texture2D texture; // Characters texture atlas Texture2D texture; // Texture atlas containing the glyphs
Rectangle *recs; // Characters rectangles in texture Rectangle *recs; // Rectangles in texture for the glyphs
GlyphInfo *chars; // Characters glyphs info data GlyphInfo *glyphs; // Glyphs info data
} Font; } Font;
// Camera, defines position/orientation in 3d space // Camera, defines position/orientation in 3d space
@ -324,7 +318,7 @@ typedef struct Mesh {
int vertexCount; // Number of vertices stored in arrays int vertexCount; // Number of vertices stored in arrays
int triangleCount; // Number of triangles stored (indexed or not) int triangleCount; // Number of triangles stored (indexed or not)
// Default vertex data // Vertex attributes data
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
@ -1117,7 +1111,7 @@ RLAPI Vector2 GetTouchPosition(int index); // Get touch posit
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI int GetGestureDetected(void); // Get latest detected gesture
RLAPI int GetTouchPointsCount(void); // Get touch points count RLAPI int GetTouchPointCount(void); // Get touch points count
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
@ -1151,7 +1145,7 @@ RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color);
RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line defining thickness
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw a line using cubic-bezier curves in-out 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 DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color); //Draw line using quadratic bezier curves with a control point
RLAPI void DrawLineStrip(Vector2 *points, int pointsCount, Color color); // Draw lines sequence 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 DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
@ -1175,8 +1169,8 @@ RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Co
RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!) RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
RLAPI void DrawTriangleFan(Vector2 *points, int pointsCount, Color color); // Draw a triangle fan defined by points (first vertex is the center) RLAPI void DrawTriangleFan(Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
RLAPI void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawTriangleStrip(Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version) RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters
@ -1245,7 +1239,7 @@ RLAPI void ImageColorContrast(Image *image, float contrast);
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit) RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount); // Load colors palette from image as a Color array (RGBA - 32bit) RLAPI Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount); // Load colors palette from image as a Color array (RGBA - 32bit)
RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors() RLAPI void UnloadImageColors(Color *colors); // Unload color data loaded with LoadImageColors()
RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette() RLAPI void UnloadImagePalette(Color *colors); // Unload colors palette loaded with LoadImagePalette()
RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle RLAPI Rectangle GetImageAlphaBorder(Image image, float threshold); // Get image alpha border rectangle
@ -1292,7 +1286,7 @@ RLAPI void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Re
RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest. RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest.
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely
RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointsCount, Color tint); // Draw a textured polygon RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint); // Draw a textured polygon
// Color/pixel related functions // Color/pixel related functions
RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
@ -1303,7 +1297,7 @@ RLAPI Vector3 ColorToHSV(Color color); // G
RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Get a Color from HSV values, hue [0..360], saturation/value [0..1] RLAPI Color ColorFromHSV(float hue, float saturation, float value); // Get a Color from HSV values, hue [0..360], saturation/value [0..1]
RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f RLAPI Color ColorAlpha(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f
RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
RLAPI Color GetColor(int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format
@ -1315,12 +1309,12 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions // Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) 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 charsCount); // Load font from file with extended parameters RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount); // Load font from file with extended parameters
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI 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 GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use 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 charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info 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 charsCount); // Unload font chars info data (RAM) RLAPI void UnloadFontData(GlyphInfo *chars, int glyphCount); // Unload font chars info data (RAM)
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM) RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
// Text drawing functions // Text drawing functions
@ -1340,9 +1334,9 @@ RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint);
// Text codepoints management functions (unicode characters) // Text codepoints management functions (unicode characters)
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
RLAPI int GetCodepointsCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string RLAPI int GetCodepointCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength); // Encode one codepoint into UTF-8 byte array (array length returned as parameter) RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!) RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
// Text strings management functions (no UTF-8 strings, only byte chars) // Text strings management functions (no UTF-8 strings, only byte chars)
@ -1372,7 +1366,7 @@ RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color);
RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!)
RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointsCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawTriangleStrip3D(Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
@ -1440,7 +1434,7 @@ RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
// Model animations loading/unloading functions // Model animations loading/unloading functions
RLAPI ModelAnimation *LoadModelAnimations(const char *fileName, int *animsCount); // 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 UpdateModelAnimation(Model model, ModelAnimation anim, int frame); // Update model animation pose
RLAPI void UnloadModelAnimation(ModelAnimation anim); // Unload animation data 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, unsigned int count); // Unload animation array data
@ -1472,7 +1466,7 @@ RLAPI Wave LoadWave(const char *fileName); // Load wa
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
RLAPI void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data
RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSound(Sound sound); // Unload sound
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
@ -1513,7 +1507,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur
// AudioStream management functions // AudioStream management functions
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int framesCount); // Update audio stream buffers with data RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream

View File

@ -279,7 +279,7 @@ typedef enum {
// Dynamic vertex buffers (position + texcoords + colors + indices arrays) // Dynamic vertex buffers (position + texcoords + colors + indices arrays)
typedef struct rlVertexBuffer { typedef struct rlVertexBuffer {
int elementsCount; // Number of elements in the buffer (QUADS) int elementCount; // Number of elements in the buffer (QUADS)
int vCounter; // Vertex position counter to process (and draw) from full buffer int vCounter; // Vertex position counter to process (and draw) from full buffer
int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer int tcCounter; // Vertex texcoord counter to process (and draw) from full buffer
@ -316,12 +316,12 @@ typedef struct rlDrawCall {
// rlRenderBatch type // rlRenderBatch type
typedef struct rlRenderBatch { typedef struct rlRenderBatch {
int buffersCount; // Number of vertex buffers (multi-buffering support) int bufferCount; // Number of vertex buffers (multi-buffering support)
int currentBuffer; // Current buffer tracking in case of multi-buffering int currentBuffer; // Current buffer tracking in case of multi-buffering
rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data rlVertexBuffer *vertexBuffer; // Dynamic buffer(s) for vertex data
rlDrawCall *draws; // Draw calls array, depends on textureId rlDrawCall *draws; // Draw calls array, depends on textureId
int drawsCounter; // Draw calls counter int drawCounter; // Draw calls counter
float currentDepth; // Current depth value for next draw float currentDepth; // Current depth value for next draw
} rlRenderBatch; } rlRenderBatch;
@ -1210,34 +1210,34 @@ void rlBegin(int mode)
{ {
// Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS // Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
// NOTE: In all three cases, vertex are accumulated over default internal vertex buffer // NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode != mode) if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode != mode)
{ {
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
{ {
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing // that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw, // It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset // those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn // for the next set of vertex to be drawn
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
{ {
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->drawsCounter++; RLGL.currentBatch->drawCounter++;
} }
} }
if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode = mode; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode = mode;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = RLGL.State.defaultTextureId; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = RLGL.State.defaultTextureId;
} }
} }
@ -1285,7 +1285,7 @@ void rlEnd(void)
// Verify internal buffers limits // Verify internal buffers limits
// NOTE: This check is combined with usage of rlCheckRenderBatchLimit() // NOTE: This check is combined with usage of rlCheckRenderBatchLimit()
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >= if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter) >=
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4 - 4)) (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4 - 4))
{ {
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(), // WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlDrawRenderBatch(),
// we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call! // we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
@ -1312,14 +1312,14 @@ void rlVertex3f(float x, float y, float z)
} }
// Verify that current vertex buffer elements limit has not been reached // Verify that current vertex buffer elements limit has not been reached
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter < (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
{ {
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = tx; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter] = tx;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = ty; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 1] = ty;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = tz; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vertices[3*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + 2] = tz;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter++;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount++; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount++;
} }
else TRACELOG(RL_LOG_ERROR, "RLGL: Batch elements overflow"); else TRACELOG(RL_LOG_ERROR, "RLGL: Batch elements overflow");
} }
@ -1390,7 +1390,7 @@ void rlSetTexture(unsigned int id)
#else #else
// NOTE: If quads batch limit is reached, we force a draw call and next batch starts // NOTE: If quads batch limit is reached, we force a draw call and next batch starts
if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >= if (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter >=
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4) RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4)
{ {
rlDrawRenderBatch(RLGL.currentBatch); rlDrawRenderBatch(RLGL.currentBatch);
} }
@ -1401,33 +1401,33 @@ void rlSetTexture(unsigned int id)
#if defined(GRAPHICS_API_OPENGL_11) #if defined(GRAPHICS_API_OPENGL_11)
rlEnableTexture(id); rlEnableTexture(id);
#else #else
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId != id) if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId != id)
{ {
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount > 0) if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount > 0)
{ {
// Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4, // Make sure current RLGL.currentBatch->draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing // that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw, // It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset // those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn // for the next set of vertex to be drawn
if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4); if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_LINES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount : RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4);
else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount%4))); else if (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].mode == RL_TRIANGLES) RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = ((RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount%4)));
else RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment = 0; else RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment = 0;
if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment)) if (!rlCheckRenderBatchLimit(RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment))
{ {
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexAlignment; RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].tcCounter += RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexAlignment;
RLGL.currentBatch->drawsCounter++; RLGL.currentBatch->drawCounter++;
} }
} }
if (RLGL.currentBatch->drawsCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch); if (RLGL.currentBatch->drawCounter >= RL_DEFAULT_BATCH_DRAWCALLS) rlDrawRenderBatch(RLGL.currentBatch);
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].textureId = id; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].textureId = id;
RLGL.currentBatch->draws[RLGL.currentBatch->drawsCounter - 1].vertexCount = 0; RLGL.currentBatch->draws[RLGL.currentBatch->drawCounter - 1].vertexCount = 0;
} }
#endif #endif
} }
@ -1910,12 +1910,12 @@ void rlLoadExtensions(void *loader)
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
// NOTE: We have to duplicate string because glGetString() returns a const string // NOTE: We have to duplicate string because glGetString() returns a const string
int len = strlen(extensions) + 1; int size = strlen(extensions) + 1; // Get extensions string size in bytes
char *extensionsDup = (char *)RL_CALLOC(len, sizeof(char)); char *extensionsDup = (char *)RL_CALLOC(size, sizeof(char));
strcpy(extensionsDup, extensions); strcpy(extensionsDup, extensions);
extList[numExt] = extensionsDup; extList[numExt] = extensionsDup;
for (int i = 0; i < len; i++) for (int i = 0; i < size; i++)
{ {
if (extensionsDup[i] == ' ') if (extensionsDup[i] == ' ')
{ {
@ -2169,7 +2169,7 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
for (int i = 0; i < numBuffers; i++) for (int i = 0; i < numBuffers; i++)
{ {
batch.vertexBuffer[i].elementsCount = bufferElements; batch.vertexBuffer[i].elementCount = bufferElements;
batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad batch.vertexBuffer[i].vertices = (float *)RL_MALLOC(bufferElements*3*4*sizeof(float)); // 3 float by vertex, 4 vertex by quad
batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad batch.vertexBuffer[i].texcoords = (float *)RL_MALLOC(bufferElements*2*4*sizeof(float)); // 2 float by texcoord, 4 texcoord by quad
@ -2274,8 +2274,8 @@ rlRenderBatch rlLoadRenderBatch(int numBuffers, int bufferElements)
//batch.draws[i].RLGL.State.modelview = rlMatrixIdentity(); //batch.draws[i].RLGL.State.modelview = rlMatrixIdentity();
} }
batch.buffersCount = numBuffers; // Record buffer count batch.bufferCount = numBuffers; // Record buffer count
batch.drawsCounter = 1; // Reset draws counter batch.drawCounter = 1; // Reset draws counter
batch.currentDepth = -1.0f; // Reset depth value batch.currentDepth = -1.0f; // Reset depth value
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
#endif #endif
@ -2297,7 +2297,7 @@ void rlUnloadRenderBatch(rlRenderBatch batch)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// Unload all vertex buffers data // Unload all vertex buffers data
for (int i = 0; i < batch.buffersCount; i++) for (int i = 0; i < batch.bufferCount; i++)
{ {
// Delete VBOs from GPU (VRAM) // Delete VBOs from GPU (VRAM)
glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]); glDeleteBuffers(1, &batch.vertexBuffer[i].vboId[0]);
@ -2338,17 +2338,17 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
// Vertex positions buffer // Vertex positions buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices); glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*3*sizeof(float), batch->vertexBuffer[batch->currentBuffer].vertices);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
// Texture coordinates buffer // Texture coordinates buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords); glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*2*sizeof(float), batch->vertexBuffer[batch->currentBuffer].texcoords);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
// Colors buffer // Colors buffer
glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, batch->vertexBuffer[batch->currentBuffer].vboId[2]);
glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors); glBufferSubData(GL_ARRAY_BUFFER, 0, batch->vertexBuffer[batch->currentBuffer].vCounter*4*sizeof(unsigned char), batch->vertexBuffer[batch->currentBuffer].colors);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementsCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*batch->vertexBuffer[batch->currentBuffer].elementCount, batch->vertexBuffer[batch->currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
// NOTE: glMapBuffer() causes sync issue. // NOTE: glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job. // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
@ -2375,12 +2375,12 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
Matrix matProjection = RLGL.State.projection; Matrix matProjection = RLGL.State.projection;
Matrix matModelView = RLGL.State.modelview; Matrix matModelView = RLGL.State.modelview;
int eyesCount = 1; int eyeCount = 1;
if (RLGL.State.stereoRender) eyesCount = 2; if (RLGL.State.stereoRender) eyeCount = 2;
for (int eye = 0; eye < eyesCount; eye++) for (int eye = 0; eye < eyeCount; eye++)
{ {
if (eyesCount == 2) if (eyeCount == 2)
{ {
// Setup current eye viewport (half screen width) // Setup current eye viewport (half screen width)
rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight); rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
@ -2447,7 +2447,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
// NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls // NOTE: Batch system accumulates calls by texture0 changes, additional textures are enabled for all the draw calls
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
for (int i = 0, vertexOffset = 0; i < batch->drawsCounter; i++) for (int i = 0, vertexOffset = 0; i < batch->drawCounter; i++)
{ {
// Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default // Bind current draw call texture, activated as GL_TEXTURE0 and binded to sampler2D texture0 by default
glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId); glBindTexture(GL_TEXTURE_2D, batch->draws[i].textureId);
@ -2456,7 +2456,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
else else
{ {
#if defined(GRAPHICS_API_OPENGL_33) #if defined(GRAPHICS_API_OPENGL_33)
// We need to define the number of indices to be processed: quadsCount*6 // We need to define the number of indices to be processed: elementCount*6
// NOTE: The final parameter tells the GPU the offset in bytes from the // NOTE: The final parameter tells the GPU the offset in bytes from the
// start of the index buffer to the location of the first index to process // start of the index buffer to the location of the first index to process
glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint))); glDrawElements(GL_TRIANGLES, batch->draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(vertexOffset/4*6*sizeof(GLuint)));
@ -2510,12 +2510,12 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0; for (int i = 0; i < RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS; i++) RLGL.State.activeTextureId[i] = 0;
// Reset draws counter to one draw for the batch // Reset draws counter to one draw for the batch
batch->drawsCounter = 1; batch->drawCounter = 1;
//------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------
// Change to next buffer in the list (in case of multi-buffering) // Change to next buffer in the list (in case of multi-buffering)
batch->currentBuffer++; batch->currentBuffer++;
if (batch->currentBuffer >= batch->buffersCount) batch->currentBuffer = 0; if (batch->currentBuffer >= batch->bufferCount) batch->currentBuffer = 0;
#endif #endif
} }
@ -2546,7 +2546,7 @@ bool rlCheckRenderBatchLimit(int vCount)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >= if ((RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].vCounter + vCount) >=
(RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementsCount*4)) (RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].elementCount*4))
{ {
overflow = true; overflow = true;
rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside rlDrawRenderBatch(RLGL.currentBatch); // NOTE: Stereo rendering is checked inside
@ -2956,9 +2956,9 @@ void rlGenTextureMipmaps(unsigned int id, int width, int height, int format, int
*mipmaps = mipmapCount + 1; *mipmaps = mipmapCount + 1;
RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data RL_FREE(texData); // Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", texture->id, texture->mipmaps); TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Mipmaps generated manually on CPU side, total: %i", id, *mipmaps);
} }
else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", texture->id); else TRACELOG(RL_LOG_WARNING, "TEXTURE: [ID %i] Failed to generate mipmaps for provided texture format", id);
} }
#endif #endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)

View File

@ -190,16 +190,16 @@ void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, fl
} }
// Draw lines sequence // Draw lines sequence
void DrawLineStrip(Vector2 *points, int pointsCount, Color color) void DrawLineStrip(Vector2 *points, int pointCount, Color color)
{ {
if (pointsCount >= 2) if (pointCount >= 2)
{ {
rlCheckRenderBatchLimit(pointsCount); rlCheckRenderBatchLimit(pointCount);
rlBegin(RL_LINES); rlBegin(RL_LINES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < pointsCount - 1; i++) for (int i = 0; i < pointCount - 1; i++)
{ {
rlVertex2f(points[i].x, points[i].y); rlVertex2f(points[i].x, points[i].y);
rlVertex2f(points[i + 1].x, points[i + 1].y); rlVertex2f(points[i + 1].x, points[i + 1].y);
@ -1318,17 +1318,17 @@ void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
// Draw a triangle fan defined by points // Draw a triangle fan defined by points
// NOTE: First vertex provided is the center, shared by all triangles // NOTE: First vertex provided is the center, shared by all triangles
// By default, following vertex should be provided in counter-clockwise order // By default, following vertex should be provided in counter-clockwise order
void DrawTriangleFan(Vector2 *points, int pointsCount, Color color) void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
{ {
if (pointsCount >= 3) if (pointCount >= 3)
{ {
rlCheckRenderBatchLimit((pointsCount - 2)*4); rlCheckRenderBatchLimit((pointCount - 2)*4);
rlSetTexture(texShapes.id); rlSetTexture(texShapes.id);
rlBegin(RL_QUADS); rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 1; i < pointsCount - 1; i++) for (int i = 1; i < pointCount - 1; i++)
{ {
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height); rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
rlVertex2f(points[0].x, points[0].y); rlVertex2f(points[0].x, points[0].y);
@ -1349,16 +1349,16 @@ void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
// Draw a triangle strip defined by points // Draw a triangle strip defined by points
// NOTE: Every new vertex connects with previous two // NOTE: Every new vertex connects with previous two
void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color) void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
{ {
if (pointsCount >= 3) if (pointCount >= 3)
{ {
rlCheckRenderBatchLimit(3*(pointsCount - 2)); rlCheckRenderBatchLimit(3*(pointCount - 2));
rlBegin(RL_TRIANGLES); rlBegin(RL_TRIANGLES);
rlColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = 2; i < pointsCount; i++) for (int i = 2; i < pointCount; i++)
{ {
if ((i%2) == 0) if ((i%2) == 0)
{ {

View File

@ -192,7 +192,8 @@ jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaB
<script type='text/javascript'> <script type='text/javascript'>
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
{ {
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); var isSafari = false; // Not supported, navigator.userAgent access is being restricted
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
var data = FS.readFile(memoryFSname); var data = FS.readFile(memoryFSname);
var blob; var blob;

View File

@ -129,8 +129,8 @@ extern void LoadFontDefault(void)
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl // Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
defaultFont.charsCount = 224; // Number of chars included in our default font defaultFont.glyphCount = 224; // Number of chars included in our default font
defaultFont.charsPadding = 0; // Characters padding defaultFont.glyphPadding = 0; // Characters padding
// Default font is directly defined here (data generated from a sprite font image) // Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct Font without creating large global variables // This way, we reconstruct Font without creating large global variables
@ -220,21 +220,21 @@ extern void LoadFontDefault(void)
defaultFont.texture = LoadTextureFromImage(imFont); defaultFont.texture = LoadTextureFromImage(imFont);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, charsCount // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, glyphCount
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Allocate space for our characters info data // Allocate space for our characters info data
// NOTE: This memory should be freed at end! --> CloseWindow() // NOTE: This memory should be freed at end! --> CloseWindow()
defaultFont.chars = (GlyphInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(GlyphInfo)); defaultFont.glyphs = (GlyphInfo *)RL_MALLOC(defaultFont.glyphCount*sizeof(GlyphInfo));
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle)); defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.glyphCount*sizeof(Rectangle));
int currentLine = 0; int currentLine = 0;
int currentPosX = charsDivisor; int currentPosX = charsDivisor;
int testPosX = charsDivisor; int testPosX = charsDivisor;
for (int i = 0; i < defaultFont.charsCount; i++) for (int i = 0; i < defaultFont.glyphCount; i++)
{ {
defaultFont.chars[i].value = 32 + i; // First char is 32 defaultFont.glyphs[i].value = 32 + i; // First char is 32
defaultFont.recs[i].x = (float)currentPosX; defaultFont.recs[i].x = (float)currentPosX;
defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor)); defaultFont.recs[i].y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
@ -255,12 +255,12 @@ extern void LoadFontDefault(void)
else currentPosX = testPosX; else currentPosX = testPosX;
// NOTE: On default font character offsets and xAdvance are not required // NOTE: On default font character offsets and xAdvance are not required
defaultFont.chars[i].offsetX = 0; defaultFont.glyphs[i].offsetX = 0;
defaultFont.chars[i].offsetY = 0; defaultFont.glyphs[i].offsetY = 0;
defaultFont.chars[i].advanceX = 0; defaultFont.glyphs[i].advanceX = 0;
// Fill character image data from fontClear data // Fill character image data from fontClear data
defaultFont.chars[i].image = ImageFromImage(imFont, defaultFont.recs[i]); defaultFont.glyphs[i].image = ImageFromImage(imFont, defaultFont.recs[i]);
} }
UnloadImage(imFont); UnloadImage(imFont);
@ -273,9 +273,9 @@ extern void LoadFontDefault(void)
// Unload raylib default font // Unload raylib default font
extern void UnloadFontDefault(void) extern void UnloadFontDefault(void)
{ {
for (int i = 0; i < defaultFont.charsCount; i++) UnloadImage(defaultFont.chars[i].image); for (int i = 0; i < defaultFont.glyphCount; i++) UnloadImage(defaultFont.glyphs[i].image);
UnloadTexture(defaultFont.texture); UnloadTexture(defaultFont.texture);
RL_FREE(defaultFont.chars); RL_FREE(defaultFont.glyphs);
RL_FREE(defaultFont.recs); RL_FREE(defaultFont.recs);
} }
#endif // SUPPORT_DEFAULT_FONT #endif // SUPPORT_DEFAULT_FONT
@ -337,7 +337,7 @@ Font LoadFont(const char *fileName)
// Load Font from TTF font file with generation parameters // 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 // 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 // if array is NULL, default char set is selected 32..126
Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount) Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int glyphCount)
{ {
Font font = { 0 }; Font font = { 0 };
@ -348,7 +348,7 @@ Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCou
if (fileData != NULL) if (fileData != NULL)
{ {
// Loading font from memory data // Loading font from memory data
font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, charsCount); font = LoadFontFromMemory(GetFileExtension(fileName), fileData, fileSize, fontSize, fontChars, glyphCount);
RL_FREE(fileData); RL_FREE(fileData);
} }
@ -449,28 +449,28 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
Font font = { 0 }; Font font = { 0 };
font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture font.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
font.charsCount = index; font.glyphCount = index;
font.charsPadding = 0; font.glyphPadding = 0;
// We got tempCharValues and tempCharsRecs populated with chars data // We got tempCharValues and tempCharsRecs populated with chars data
// Now we move temp data to sized charValues and charRecs arrays // Now we move temp data to sized charValues and charRecs arrays
font.chars = (GlyphInfo *)RL_MALLOC(font.charsCount*sizeof(GlyphInfo)); font.glyphs = (GlyphInfo *)RL_MALLOC(font.glyphCount*sizeof(GlyphInfo));
font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle)); font.recs = (Rectangle *)RL_MALLOC(font.glyphCount*sizeof(Rectangle));
for (int i = 0; i < font.charsCount; i++) for (int i = 0; i < font.glyphCount; i++)
{ {
font.chars[i].value = tempCharValues[i]; font.glyphs[i].value = tempCharValues[i];
// Get character rectangle in the font atlas texture // Get character rectangle in the font atlas texture
font.recs[i] = tempCharRecs[i]; font.recs[i] = tempCharRecs[i];
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
font.chars[i].offsetX = 0; font.glyphs[i].offsetX = 0;
font.chars[i].offsetY = 0; font.glyphs[i].offsetY = 0;
font.chars[i].advanceX = 0; font.glyphs[i].advanceX = 0;
// Fill character image data from fontClear data // Fill character image data from fontClear data
font.chars[i].image = ImageFromImage(fontClear, tempCharRecs[i]); font.glyphs[i].image = ImageFromImage(fontClear, tempCharRecs[i]);
} }
UnloadImage(fontClear); // Unload processed image once converted to texture UnloadImage(fontClear); // Unload processed image once converted to texture
@ -481,7 +481,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
} }
// Load font from memory buffer, fileType refers to extension: i.e. ".ttf" // 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 charsCount) Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount)
{ {
Font font = { 0 }; Font font = { 0 };
@ -493,22 +493,22 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
TextIsEqual(fileExtLower, ".otf")) TextIsEqual(fileExtLower, ".otf"))
{ {
font.baseSize = fontSize; font.baseSize = fontSize;
font.charsCount = (charsCount > 0)? charsCount : 95; font.glyphCount = (glyphCount > 0)? glyphCount : 95;
font.charsPadding = 0; font.glyphPadding = 0;
font.chars = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT); font.glyphs = LoadFontData(fileData, dataSize, font.baseSize, fontChars, font.glyphCount, FONT_DEFAULT);
if (font.chars != NULL) if (font.glyphs != NULL)
{ {
font.charsPadding = FONT_TTF_DEFAULT_CHARS_PADDING; font.glyphPadding = FONT_TTF_DEFAULT_CHARS_PADDING;
Image atlas = GenImageFontAtlas(font.chars, &font.recs, font.charsCount, font.baseSize, font.charsPadding, 0); Image atlas = GenImageFontAtlas(font.glyphs, &font.recs, font.glyphCount, font.baseSize, font.glyphPadding, 0);
font.texture = LoadTextureFromImage(atlas); font.texture = LoadTextureFromImage(atlas);
// Update chars[i].image to use alpha, required to be used on ImageDrawText() // Update glyphs[i].image to use alpha, required to be used on ImageDrawText()
for (int i = 0; i < font.charsCount; i++) for (int i = 0; i < font.glyphCount; i++)
{ {
UnloadImage(font.chars[i].image); UnloadImage(font.glyphs[i].image);
font.chars[i].image = ImageFromImage(atlas, font.recs[i]); font.glyphs[i].image = ImageFromImage(atlas, font.recs[i]);
} }
UnloadImage(atlas); UnloadImage(atlas);
@ -524,7 +524,7 @@ Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int
// Load font data for further use // Load font data for further use
// NOTE: Requires TTF font memory data and can generate SDF data // NOTE: Requires TTF font memory data and can generate SDF data
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type) GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int glyphCount, int type)
{ {
// NOTE: Using some SDF generation default values, // NOTE: Using some SDF generation default values,
// trades off precision with ability to handle *smaller* sizes // trades off precision with ability to handle *smaller* sizes
@ -562,22 +562,22 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap); stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
// In case no chars count provided, default to 95 // In case no chars count provided, default to 95
charsCount = (charsCount > 0)? charsCount : 95; glyphCount = (glyphCount > 0)? glyphCount : 95;
// Fill fontChars in case not provided externally // Fill fontChars in case not provided externally
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space) // NOTE: By default we fill glyphCount consecutevely, starting at 32 (Space)
if (fontChars == NULL) if (fontChars == NULL)
{ {
fontChars = (int *)RL_MALLOC(charsCount*sizeof(int)); fontChars = (int *)RL_MALLOC(glyphCount*sizeof(int));
for (int i = 0; i < charsCount; i++) fontChars[i] = i + 32; for (int i = 0; i < glyphCount; i++) fontChars[i] = i + 32;
genFontChars = true; genFontChars = true;
} }
chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); chars = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
// NOTE: Using simple packaging, one char after another // NOTE: Using simple packaging, one char after another
for (int i = 0; i < charsCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
int chw = 0, chh = 0; // Character width and height (on generation) int chw = 0, chh = 0; // Character width and height (on generation)
int ch = fontChars[i]; // Character value to get info for int ch = fontChars[i]; // Character value to get info for
@ -650,7 +650,7 @@ GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSiz
// Generate image font atlas using chars info // Generate image font atlas using chars info
// NOTE: Packing method: 0-Default, 1-Skyline // NOTE: Packing method: 0-Default, 1-Skyline
#if defined(SUPPORT_FILEFORMAT_TTF) #if defined(SUPPORT_FILEFORMAT_TTF)
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod) Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphCount, int fontSize, int padding, int packMethod)
{ {
Image atlas = { 0 }; Image atlas = { 0 };
@ -663,17 +663,17 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
*charRecs = NULL; *charRecs = NULL;
// In case no chars count provided we suppose default of 95 // In case no chars count provided we suppose default of 95
charsCount = (charsCount > 0)? charsCount : 95; glyphCount = (glyphCount > 0)? glyphCount : 95;
// NOTE: Rectangles memory is loaded here! // NOTE: Rectangles memory is loaded here!
Rectangle *recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle)); Rectangle *recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
// Calculate image size based on required pixel area // Calculate image size based on required pixel area
// NOTE 1: Image is forced to be squared and POT... very conservative! // NOTE 1: Image is forced to be squared and POT... very conservative!
// NOTE 2: SDF font characters already contain an internal padding, // NOTE 2: SDF font characters already contain an internal padding,
// so image size would result bigger than default font type // so image size would result bigger than default font type
float requiredArea = 0; float requiredArea = 0;
for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding)); for (int i = 0; i < glyphCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
float guessSize = sqrtf(requiredArea)*1.3f; float guessSize = sqrtf(requiredArea)*1.3f;
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
@ -692,7 +692,7 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
int offsetY = padding; int offsetY = padding;
// NOTE: Using simple packaging, one char after another // NOTE: Using simple packaging, one char after another
for (int i = 0; i < charsCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
// Copy pixel data from fc.data to atlas // Copy pixel data from fc.data to atlas
for (int y = 0; y < chars[i].image.height; y++) for (int y = 0; y < chars[i].image.height; y++)
@ -728,13 +728,13 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect) else if (packMethod == 1) // Use Skyline rect packing algorythm (stb_pack_rect)
{ {
stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context)); stbrp_context *context = (stbrp_context *)RL_MALLOC(sizeof(*context));
stbrp_node *nodes = (stbrp_node *)RL_MALLOC(charsCount*sizeof(*nodes)); stbrp_node *nodes = (stbrp_node *)RL_MALLOC(glyphCount*sizeof(*nodes));
stbrp_init_target(context, atlas.width, atlas.height, nodes, charsCount); stbrp_init_target(context, atlas.width, atlas.height, nodes, glyphCount);
stbrp_rect *rects = (stbrp_rect *)RL_MALLOC(charsCount*sizeof(stbrp_rect)); stbrp_rect *rects = (stbrp_rect *)RL_MALLOC(glyphCount*sizeof(stbrp_rect));
// Fill rectangles for packaging // Fill rectangles for packaging
for (int i = 0; i < charsCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
rects[i].id = i; rects[i].id = i;
rects[i].w = chars[i].image.width + 2*padding; rects[i].w = chars[i].image.width + 2*padding;
@ -742,9 +742,9 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
} }
// Package rectangles into atlas // Package rectangles into atlas
stbrp_pack_rects(context, rects, charsCount); stbrp_pack_rects(context, rects, glyphCount);
for (int i = 0; i < charsCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
// It return char rectangles in atlas // It return char rectangles in atlas
recs[i].x = rects[i].x + (float)padding; recs[i].x = rects[i].x + (float)padding;
@ -792,12 +792,12 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsC
} }
#endif #endif
// Unload font chars info data (RAM) // Unload font glyphs info data (RAM)
void UnloadFontData(GlyphInfo *chars, int charsCount) void UnloadFontData(GlyphInfo *glyphs, int glyphCount)
{ {
for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image); for (int i = 0; i < glyphCount; i++) UnloadImage(glyphs[i].image);
RL_FREE(chars); RL_FREE(glyphs);
} }
// Unload Font from GPU memory (VRAM) // Unload Font from GPU memory (VRAM)
@ -806,7 +806,7 @@ void UnloadFont(Font font)
// NOTE: Make sure font is not default font (fallback) // NOTE: Make sure font is not default font (fallback)
if (font.texture.id != GetFontDefault().texture.id) if (font.texture.id != GetFontDefault().texture.id)
{ {
UnloadFontData(font.chars, font.charsCount); UnloadFontData(font.glyphs, font.glyphCount);
UnloadTexture(font.texture); UnloadTexture(font.texture);
RL_FREE(font.recs); RL_FREE(font.recs);
@ -851,14 +851,14 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
{ {
if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop
int textOffsetY = 0; // Offset between lines (on line break '\n') int textOffsetY = 0; // Offset between lines (on line break '\n')
float textOffsetX = 0.0f; // Offset X to next character to draw float textOffsetX = 0.0f; // Offset X to next character to draw
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
for (int i = 0; i < length;) for (int i = 0; i < size;)
{ {
// Get next codepoint from byte string and glyph index in font // Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0; int codepointByteCount = 0;
@ -883,8 +883,8 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint); DrawTextCodepoint(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint);
} }
if (font.chars[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing); if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing);
else textOffsetX += ((float)font.chars[index].advanceX*scaleFactor + spacing); else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing);
} }
i += codepointByteCount; // Move text bytes counter to next codepoint i += codepointByteCount; // Move text bytes counter to next codepoint
@ -914,16 +914,16 @@ void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSiz
float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor
// Character destination rectangle on screen // Character destination rectangle on screen
// NOTE: We consider charsPadding on drawing // NOTE: We consider glyphPadding on drawing
Rectangle dstRec = { position.x + font.chars[index].offsetX*scaleFactor - (float)font.charsPadding*scaleFactor, Rectangle dstRec = { position.x + font.glyphs[index].offsetX*scaleFactor - (float)font.glyphPadding*scaleFactor,
position.y + font.chars[index].offsetY*scaleFactor - (float)font.charsPadding*scaleFactor, position.y + font.glyphs[index].offsetY*scaleFactor - (float)font.glyphPadding*scaleFactor,
(font.recs[index].width + 2.0f*font.charsPadding)*scaleFactor, (font.recs[index].width + 2.0f*font.glyphPadding)*scaleFactor,
(font.recs[index].height + 2.0f*font.charsPadding)*scaleFactor }; (font.recs[index].height + 2.0f*font.glyphPadding)*scaleFactor };
// Character source rectangle from font texture atlas // Character source rectangle from font texture atlas
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects // NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
Rectangle srcRec = { font.recs[index].x - (float)font.charsPadding, font.recs[index].y - (float)font.charsPadding, Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
font.recs[index].width + 2.0f*font.charsPadding, font.recs[index].height + 2.0f*font.charsPadding }; font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding };
// Draw the character texture on the screen // Draw the character texture on the screen
DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint); DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint);
@ -950,9 +950,9 @@ int MeasureText(const char *text, int fontSize)
// Measure string size for Font // Measure string size for Font
Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing) Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing)
{ {
int len = TextLength(text); int size = TextLength(text); // Get size in bytes of text
int tempLen = 0; // Used to count longer text line num chars int tempByteCounter = 0; // Used to count longer text line num chars
int lenCounter = 0; int byteCounter = 0;
float textWidth = 0.0f; float textWidth = 0.0f;
float tempTextWidth = 0.0f; // Used to count longer text line width float tempTextWidth = 0.0f; // Used to count longer text line width
@ -963,9 +963,9 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
int letter = 0; // Current character int letter = 0; // Current character
int index = 0; // Index position in sprite font int index = 0; // Index position in sprite font
for (int i = 0; i < len; i++) for (int i = 0; i < size; i++)
{ {
lenCounter++; byteCounter++;
int next = 0; int next = 0;
letter = GetCodepoint(&text[i], &next); letter = GetCodepoint(&text[i], &next);
@ -978,24 +978,24 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
if (letter != '\n') if (letter != '\n')
{ {
if (font.chars[index].advanceX != 0) textWidth += font.chars[index].advanceX; if (font.glyphs[index].advanceX != 0) textWidth += font.glyphs[index].advanceX;
else textWidth += (font.recs[index].width + font.chars[index].offsetX); else textWidth += (font.recs[index].width + font.glyphs[index].offsetX);
} }
else else
{ {
if (tempTextWidth < textWidth) tempTextWidth = textWidth; if (tempTextWidth < textWidth) tempTextWidth = textWidth;
lenCounter = 0; byteCounter = 0;
textWidth = 0; textWidth = 0;
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
} }
if (tempLen < lenCounter) tempLen = lenCounter; if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
} }
if (tempTextWidth < textWidth) tempTextWidth = textWidth; if (tempTextWidth < textWidth) tempTextWidth = textWidth;
Vector2 vec = { 0 }; Vector2 vec = { 0 };
vec.x = tempTextWidth*scaleFactor + (float)((tempLen - 1)*spacing); // Adds chars spacing to measure vec.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
vec.y = textHeight*scaleFactor; vec.y = textHeight*scaleFactor;
return vec; return vec;
@ -1014,9 +1014,9 @@ int GetGlyphIndex(Font font, int codepoint)
#if defined(SUPPORT_UNORDERED_CHARSET) #if defined(SUPPORT_UNORDERED_CHARSET)
int index = GLYPH_NOTFOUND_CHAR_FALLBACK; int index = GLYPH_NOTFOUND_CHAR_FALLBACK;
for (int i = 0; i < font.charsCount; i++) for (int i = 0; i < font.glyphCount; i++)
{ {
if (font.chars[i].value == codepoint) if (font.glyphs[i].value == codepoint)
{ {
index = i; index = i;
break; break;
@ -1035,7 +1035,7 @@ GlyphInfo GetGlyphInfo(Font font, int codepoint)
{ {
GlyphInfo info = { 0 }; GlyphInfo info = { 0 };
info = font.chars[GetGlyphIndex(font, codepoint)]; info = font.glyphs[GetGlyphIndex(font, codepoint)];
return info; return info;
} }
@ -1429,28 +1429,28 @@ char *TextCodepointsToUTF8(int *codepoints, int length)
// Encode codepoint into utf8 text (char array length returned as parameter) // Encode codepoint into utf8 text (char array length returned as parameter)
// NOTE: It uses a static array to store UTF-8 bytes // NOTE: It uses a static array to store UTF-8 bytes
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength) RLAPI const char *CodepointToUTF8(int codepoint, int *byteSize)
{ {
static char utf8[6] = { 0 }; static char utf8[6] = { 0 };
int length = 0; int size = 0; // Byte size of codepoint
if (codepoint <= 0x7f) if (codepoint <= 0x7f)
{ {
utf8[0] = (char)codepoint; utf8[0] = (char)codepoint;
length = 1; size = 1;
} }
else if (codepoint <= 0x7ff) else if (codepoint <= 0x7ff)
{ {
utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0);
utf8[1] = (char)((codepoint & 0x3f) | 0x80); utf8[1] = (char)((codepoint & 0x3f) | 0x80);
length = 2; size = 2;
} }
else if (codepoint <= 0xffff) else if (codepoint <= 0xffff)
{ {
utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0);
utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
utf8[2] = (char)((codepoint & 0x3f) | 0x80); utf8[2] = (char)((codepoint & 0x3f) | 0x80);
length = 3; size = 3;
} }
else if (codepoint <= 0x10ffff) else if (codepoint <= 0x10ffff)
{ {
@ -1458,10 +1458,10 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength)
utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80);
utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80);
utf8[3] = (char)((codepoint & 0x3f) | 0x80); utf8[3] = (char)((codepoint & 0x3f) | 0x80);
length = 4; size = 4;
} }
*byteLength = length; *byteSize = size;
return utf8; return utf8;
} }
@ -1472,22 +1472,22 @@ int *LoadCodepoints(const char *text, int *count)
int textLength = TextLength(text); int textLength = TextLength(text);
int bytesProcessed = 0; int bytesProcessed = 0;
int codepointsCount = 0; int codepointCount = 0;
// Allocate a big enough buffer to store as many codepoints as text bytes // Allocate a big enough buffer to store as many codepoints as text bytes
int *codepoints = RL_CALLOC(textLength, sizeof(int)); int *codepoints = RL_CALLOC(textLength, sizeof(int));
for (int i = 0; i < textLength; codepointsCount++) for (int i = 0; i < textLength; codepointCount++)
{ {
codepoints[codepointsCount] = GetCodepoint(text + i, &bytesProcessed); codepoints[codepointCount] = GetCodepoint(text + i, &bytesProcessed);
i += bytesProcessed; i += bytesProcessed;
} }
// Re-allocate buffer to the actual number of codepoints loaded // Re-allocate buffer to the actual number of codepoints loaded
void *temp = RL_REALLOC(codepoints, codepointsCount*sizeof(int)); void *temp = RL_REALLOC(codepoints, codepointCount*sizeof(int));
if (temp != NULL) codepoints = temp; if (temp != NULL) codepoints = temp;
*count = codepointsCount; *count = codepointCount;
return codepoints; return codepoints;
} }
@ -1500,9 +1500,9 @@ void UnloadCodepoints(int *codepoints)
// Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found // Get total number of characters(codepoints) in a UTF-8 encoded text, until '\0' is found
// NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead // NOTE: If an invalid UTF-8 sequence is encountered a '?'(0x3f) codepoint is counted instead
int GetCodepointsCount(const char *text) int GetCodepointCount(const char *text)
{ {
unsigned int len = 0; unsigned int length = 0;
char *ptr = (char *)&text[0]; char *ptr = (char *)&text[0];
while (*ptr != '\0') while (*ptr != '\0')
@ -1513,10 +1513,10 @@ int GetCodepointsCount(const char *text)
if (letter == 0x3f) ptr += 1; if (letter == 0x3f) ptr += 1;
else ptr += next; else ptr += next;
len++; length++;
} }
return len; return length;
} }
#endif // SUPPORT_TEXT_MANIPULATION #endif // SUPPORT_TEXT_MANIPULATION
@ -1657,7 +1657,7 @@ static Font LoadBMFont(const char *fileName)
char *searchPoint = NULL; char *searchPoint = NULL;
int fontSize = 0; int fontSize = 0;
int charsCount = 0; int glyphCount = 0;
int imWidth = 0; int imWidth = 0;
int imHeight = 0; int imHeight = 0;
@ -1694,10 +1694,10 @@ static Font LoadBMFont(const char *fileName)
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
searchPoint = strstr(buffer, "count"); searchPoint = strstr(buffer, "count");
sscanf(searchPoint, "count=%i", &charsCount); sscanf(searchPoint, "count=%i", &glyphCount);
fileTextPtr += (lineBytes + 1); fileTextPtr += (lineBytes + 1);
TRACELOGD(" > Chars count: %i", charsCount); TRACELOGD(" > Chars count: %i", glyphCount);
// Compose correct path using route of .fnt file (fileName) and imFileName // Compose correct path using route of .fnt file (fileName) and imFileName
char *imPath = NULL; char *imPath = NULL;
@ -1746,14 +1746,14 @@ static Font LoadBMFont(const char *fileName)
// Fill font characters info data // Fill font characters info data
font.baseSize = fontSize; font.baseSize = fontSize;
font.charsCount = charsCount; font.glyphCount = glyphCount;
font.charsPadding = 0; font.glyphPadding = 0;
font.chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo)); font.glyphs = (GlyphInfo *)RL_MALLOC(glyphCount*sizeof(GlyphInfo));
font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle)); font.recs = (Rectangle *)RL_MALLOC(glyphCount*sizeof(Rectangle));
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
for (int i = 0; i < charsCount; i++) for (int i = 0; i < glyphCount; i++)
{ {
lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE); lineBytes = GetLine(fileTextPtr, buffer, MAX_BUFFER_SIZE);
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
@ -1764,13 +1764,13 @@ static Font LoadBMFont(const char *fileName)
font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight }; font.recs[i] = (Rectangle){ (float)charX, (float)charY, (float)charWidth, (float)charHeight };
// Save data properly in sprite font // Save data properly in sprite font
font.chars[i].value = charId; font.glyphs[i].value = charId;
font.chars[i].offsetX = charOffsetX; font.glyphs[i].offsetX = charOffsetX;
font.chars[i].offsetY = charOffsetY; font.glyphs[i].offsetY = charOffsetY;
font.chars[i].advanceX = charAdvanceX; font.glyphs[i].advanceX = charAdvanceX;
// Fill character image data from imFont data // Fill character image data from imFont data
font.chars[i].image = ImageFromImage(imFont, font.recs[i]); font.glyphs[i].image = ImageFromImage(imFont, font.recs[i]);
} }
UnloadImage(imFont); UnloadImage(imFont);

View File

@ -102,6 +102,10 @@
#define STBI_NO_PIC #define STBI_NO_PIC
#define STBI_NO_PNM // Image format .ppm and .pgm #define STBI_NO_PNM // Image format .ppm and .pgm
#if defined(__TINYC__)
#define STBI_NO_SIMD
#endif
#if (defined(SUPPORT_FILEFORMAT_BMP) || \ #if (defined(SUPPORT_FILEFORMAT_BMP) || \
defined(SUPPORT_FILEFORMAT_PNG) || \ defined(SUPPORT_FILEFORMAT_PNG) || \
defined(SUPPORT_FILEFORMAT_TGA) || \ defined(SUPPORT_FILEFORMAT_TGA) || \
@ -254,7 +258,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int
Image LoadImageAnim(const char *fileName, int *frames) Image LoadImageAnim(const char *fileName, int *frames)
{ {
Image image = { 0 }; Image image = { 0 };
int framesCount = 1; int frameCount = 1;
#if defined(SUPPORT_FILEFORMAT_GIF) #if defined(SUPPORT_FILEFORMAT_GIF)
if (IsFileExtension(fileName, ".gif")) if (IsFileExtension(fileName, ".gif"))
@ -266,7 +270,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
{ {
int comp = 0; int comp = 0;
int **delays = NULL; int **delays = NULL;
image.data = stbi_load_gif_from_memory(fileData, dataSize, delays, &image.width, &image.height, &framesCount, &comp, 4); image.data = stbi_load_gif_from_memory(fileData, dataSize, delays, &image.width, &image.height, &frameCount, &comp, 4);
image.mipmaps = 1; image.mipmaps = 1;
image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; image.format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8;
@ -282,7 +286,7 @@ Image LoadImageAnim(const char *fileName, int *frames)
// TODO: Support APNG animated images? // TODO: Support APNG animated images?
*frames = framesCount; *frames = frameCount;
return image; return image;
} }
@ -514,19 +518,19 @@ bool ExportImageAsCode(Image image, const char *fileName)
// NOTE: Text data buffer size is estimated considering image data size in bytes // NOTE: Text data buffer size is estimated considering image data size in bytes
// and requiring 6 char bytes for every byte: "0x00, " // and requiring 6 char bytes for every byte: "0x00, "
char *txtData = (char *)RL_CALLOC(6*dataSize + 2000, sizeof(char)); char *txtData = (char *)RL_CALLOC(dataSize*6 + 2000, sizeof(char));
int bytesCount = 0; int byteCount = 0;
bytesCount += sprintf(txtData + bytesCount, "////////////////////////////////////////////////////////////////////////////////////////\n"); byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes //\n"); byteCount += sprintf(txtData + byteCount, "// ImageAsCode exporter v1.0 - Image pixel data exported as an array of bytes //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// more info and bugs-report: github.com/raysan5/raylib //\n"); byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
bytesCount += sprintf(txtData + bytesCount, "// feedback and support: ray[at]raylib.com //\n"); byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "// Copyright (c) 2020 Ramon Santamaria (@raysan5) //\n"); byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2021 Ramon Santamaria (@raysan5) //\n");
bytesCount += sprintf(txtData + bytesCount, "// //\n"); byteCount += sprintf(txtData + byteCount, "// //\n");
bytesCount += sprintf(txtData + bytesCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n"); byteCount += sprintf(txtData + byteCount, "////////////////////////////////////////////////////////////////////////////////////////\n\n");
// Get file name from path and convert variable name to uppercase // Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 }; char varFileName[256] = { 0 };
@ -534,16 +538,16 @@ bool ExportImageAsCode(Image image, const char *fileName)
for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; } for (int i = 0; varFileName[i] != '\0'; i++) if ((varFileName[i] >= 'a') && (varFileName[i] <= 'z')) { varFileName[i] = varFileName[i] - 32; }
// Add image information // Add image information
bytesCount += sprintf(txtData + bytesCount, "// Image data information\n"); byteCount += sprintf(txtData + byteCount, "// Image data information\n");
bytesCount += sprintf(txtData + bytesCount, "#define %s_WIDTH %i\n", varFileName, image.width); byteCount += sprintf(txtData + byteCount, "#define %s_WIDTH %i\n", varFileName, image.width);
bytesCount += sprintf(txtData + bytesCount, "#define %s_HEIGHT %i\n", varFileName, image.height); byteCount += sprintf(txtData + byteCount, "#define %s_HEIGHT %i\n", varFileName, image.height);
bytesCount += sprintf(txtData + bytesCount, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format); byteCount += sprintf(txtData + byteCount, "#define %s_FORMAT %i // raylib internal pixel format\n\n", varFileName, image.format);
bytesCount += sprintf(txtData + bytesCount, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize); byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, dataSize);
for (int i = 0; i < dataSize - 1; i++) bytesCount += sprintf(txtData + bytesCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]); for (int i = 0; i < dataSize - 1; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n" : "0x%x, "), ((unsigned char *)image.data)[i]);
bytesCount += sprintf(txtData + bytesCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]); byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)image.data)[dataSize - 1]);
// NOTE: Text data length exported is determined by '\0' (NULL) character // NOTE: Text data size exported is determined by '\0' (NULL) character
success = SaveFileText(fileName, txtData); success = SaveFileText(fileName, txtData);
RL_FREE(txtData); RL_FREE(txtData);
@ -761,11 +765,11 @@ Image GenImageCellular(int width, int height, int tileSize)
int seedsPerRow = width/tileSize; int seedsPerRow = width/tileSize;
int seedsPerCol = height/tileSize; int seedsPerCol = height/tileSize;
int seedsCount = seedsPerRow*seedsPerCol; int seedCount = seedsPerRow*seedsPerCol;
Vector2 *seeds = (Vector2 *)RL_MALLOC(seedsCount*sizeof(Vector2)); Vector2 *seeds = (Vector2 *)RL_MALLOC(seedCount*sizeof(Vector2));
for (int i = 0; i < seedsCount; i++) for (int i = 0; i < seedCount; i++)
{ {
int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1);
@ -1143,7 +1147,7 @@ Image ImageText(const char *text, int fontSize, Color color)
// Create an image from text (custom sprite font) // Create an image from text (custom sprite font)
Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint) Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Color tint)
{ {
int length = (int)strlen(text); int size = (int)strlen(text); // Get size in bytes of text
int textOffsetX = 0; // Image drawing position X int textOffsetX = 0; // Image drawing position X
int textOffsetY = 0; // Offset between lines (on line break '\n') int textOffsetY = 0; // Offset between lines (on line break '\n')
@ -1154,7 +1158,7 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
// Create image to store text // Create image to store text
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK); Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
for (int i = 0; i < length; i++) for (int i = 0; i < size; i++)
{ {
// Get next codepoint from byte string and glyph index in font // Get next codepoint from byte string and glyph index in font
int codepointByteCount = 0; int codepointByteCount = 0;
@ -1176,12 +1180,12 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
{ {
if ((codepoint != ' ') && (codepoint != '\t')) if ((codepoint != ' ') && (codepoint != '\t'))
{ {
Rectangle rec = { (float)(textOffsetX + font.chars[index].offsetX), (float)(textOffsetY + font.chars[index].offsetY), (float)font.recs[index].width, (float)font.recs[index].height }; Rectangle rec = { (float)(textOffsetX + font.glyphs[index].offsetX), (float)(textOffsetY + font.glyphs[index].offsetY), (float)font.recs[index].width, (float)font.recs[index].height };
ImageDraw(&imText, font.chars[index].image, (Rectangle){ 0, 0, (float)font.chars[index].image.width, (float)font.chars[index].image.height }, rec, tint); ImageDraw(&imText, font.glyphs[index].image, (Rectangle){ 0, 0, (float)font.glyphs[index].image.width, (float)font.glyphs[index].image.height }, rec, tint);
} }
if (font.chars[index].advanceX == 0) textOffsetX += (int)(font.recs[index].width + spacing); if (font.glyphs[index].advanceX == 0) textOffsetX += (int)(font.recs[index].width + spacing);
else textOffsetX += font.chars[index].advanceX + (int)spacing; else textOffsetX += font.glyphs[index].advanceX + (int)spacing;
} }
i += (codepointByteCount - 1); // Move text bytes counter to next codepoint i += (codepointByteCount - 1); // Move text bytes counter to next codepoint
@ -2181,7 +2185,7 @@ Color *LoadImageColors(Image image)
// Load colors palette from image as a Color array (RGBA - 32bit) // Load colors palette from image as a Color array (RGBA - 32bit)
// NOTE: Memory allocated should be freed using UnloadImagePalette() // NOTE: Memory allocated should be freed using UnloadImagePalette()
Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount) Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorCount)
{ {
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a)) #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
@ -2230,7 +2234,7 @@ Color *LoadImagePalette(Image image, int maxPaletteSize, int *colorsCount)
UnloadImageColors(pixels); UnloadImageColors(pixels);
} }
*colorsCount = palCount; *colorCount = palCount;
return palette; return palette;
} }
@ -3483,9 +3487,9 @@ void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest,
// Draw textured polygon, defined by vertex and texturecoordinates // Draw textured polygon, defined by vertex and texturecoordinates
// NOTE: Polygon center must have straight line path to all points // NOTE: Polygon center must have straight line path to all points
// without crossing perimeter, points must be in anticlockwise order // without crossing perimeter, points must be in anticlockwise order
void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointsCount, Color tint) void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint)
{ {
rlCheckRenderBatchLimit((pointsCount - 1)*4); rlCheckRenderBatchLimit((pointCount - 1)*4);
rlSetTexture(texture.id); rlSetTexture(texture.id);
@ -3494,7 +3498,7 @@ void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2
rlColor4ub(tint.r, tint.g, tint.b, tint.a); rlColor4ub(tint.r, tint.g, tint.b, tint.a);
for (int i = 0; i < pointsCount - 1; i++) for (int i = 0; i < pointCount - 1; i++)
{ {
rlTexCoord2f(0.5f, 0.5f); rlTexCoord2f(0.5f, 0.5f);
rlVertex2f(center.x, center.y); rlVertex2f(center.x, center.y);
@ -3707,7 +3711,7 @@ Color ColorAlphaBlend(Color dst, Color src, Color tint)
} }
// Get a Color struct from hexadecimal value // Get a Color struct from hexadecimal value
Color GetColor(int hexValue) Color GetColor(unsigned int hexValue)
{ {
Color color; Color color;