Merge branch 'master' of https://github.com/orcmid/raylib
This commit is contained in:
commit
d6c7654f96
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -57,6 +57,13 @@ packages/
|
||||||
*.a
|
*.a
|
||||||
*.bc
|
*.bc
|
||||||
*.so
|
*.so
|
||||||
|
*.so.*
|
||||||
|
|
||||||
|
# Ignore wasm data in examples/
|
||||||
|
examples/**/*.wasm
|
||||||
|
examples/**/*.data
|
||||||
|
examples/**/*.js
|
||||||
|
examples/**/*.html
|
||||||
|
|
||||||
# Ignore files build by xcode
|
# Ignore files build by xcode
|
||||||
*.mode*v*
|
*.mode*v*
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never |
|
| raylib-never | 3.0 | [Never](https://github.com/never-lang/never) | https://github.com/never-lang/raylib-never |
|
||||||
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
||||||
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib |
|
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | https://github.com/RedCubeDev-ByteSpace/Relib |
|
||||||
|
| rayex | 3.7 | [elixir](https://elixir-lang.org/) | https://github.com/shiryel/rayex |
|
||||||
| raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* |
|
| raylib.cbl | 2.0 | [COBOL](https://en.wikipedia.org/wiki/COBOL) | *[code examples](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)* |
|
||||||
|
|
||||||
### Utility Wrapers
|
### Utility Wrapers
|
||||||
|
|
|
||||||
11
CHANGELOG
11
CHANGELOG
|
|
@ -3,6 +3,17 @@ changelog
|
||||||
|
|
||||||
Current Release: raylib 3.7.0 (26 April 2021)
|
Current Release: raylib 3.7.0 (26 April 2021)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
Release: raylib 4.0 (November? 2021)
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
KEY CHANGES:
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-
|
||||||
|
|
||||||
|
Detailed changes:
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
Release: raylib 3.7 (26 April 2021)
|
Release: raylib 3.7 (26 April 2021)
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -244,7 +244,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
|
||||||
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
# --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
|
||||||
# --preload-file resources # specify a resources folder for data compilation
|
# --preload-file resources # specify a resources folder for data compilation
|
||||||
# --source-map-base # allow debugging in browser with source map
|
# --source-map-base # allow debugging in browser with source map
|
||||||
CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 $(dir $<)resources@resources
|
CFLAGS += -s USE_GLFW=3 -s ASYNCIFY -s TOTAL_MEMORY=67108864 -s FORCE_FILESYSTEM=1 --preload-file $(dir $<)resources@resources
|
||||||
|
|
||||||
# NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way,
|
# NOTE: Simple raylib examples are compiled to be interpreter with asyncify, that way,
|
||||||
# we can compile same code for ALL platforms with no change required, but, working on bigger
|
# we can compile same code for ALL platforms with no change required, but, working on bigger
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,17 @@
|
||||||
*
|
*
|
||||||
* raylib [rlgl] example - Using rlgl module as standalone module
|
* raylib [rlgl] example - Using rlgl module as standalone module
|
||||||
*
|
*
|
||||||
* NOTE: This example requires OpenGL 3.3 or ES2 versions for shaders support,
|
* rlgl library is an abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0)
|
||||||
|
* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
|
||||||
|
*
|
||||||
|
* NOTE: This example requires OpenGL 3.3 or OpenGL ES 2.0 for shaders support,
|
||||||
* OpenGL 1.1 does not support shaders but it can also be used.
|
* OpenGL 1.1 does not support shaders but it can also be used.
|
||||||
*
|
*
|
||||||
* DEPENDENCIES:
|
* DEPENDENCIES:
|
||||||
* rlgl.h - OpenGL 1.1 immediate-mode style coding translation layer
|
|
||||||
* glad.h - OpenGL extensions initialization library (required by rlgl)
|
|
||||||
* raymath.h - 3D math library (required by rlgl)
|
|
||||||
* glfw3 - Windows and context initialization library
|
* glfw3 - Windows and context initialization library
|
||||||
*
|
* rlgl.h - OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
|
||||||
* rlgl library is provided as a single-file header-only library, this library
|
* glad.h - OpenGL extensions initialization library (required by rlgl)
|
||||||
* allows coding in a pseudo-OpenGL 1.1 style while translating calls to multiple
|
* raymath.h - 3D math library
|
||||||
* OpenGL versions backends (1.1, 2.1, 3.3, ES 2.0).
|
|
||||||
*
|
*
|
||||||
* WINDOWS COMPILATION:
|
* WINDOWS COMPILATION:
|
||||||
* gcc -o rlgl_standalone.exe rlgl_standalone.c -s -Iexternal\include -I..\..\src \
|
* gcc -o rlgl_standalone.exe rlgl_standalone.c -s -Iexternal\include -I..\..\src \
|
||||||
|
|
@ -21,15 +20,16 @@
|
||||||
*
|
*
|
||||||
* APPLE COMPILATION:
|
* APPLE COMPILATION:
|
||||||
* gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \
|
* gcc -o rlgl_standalone rlgl_standalone.c -I../../src -Iexternal/include -Lexternal/lib \
|
||||||
* -lglfw3 -std=c99 -framework CoreVideo -framework OpenGL -framework OpenAL \
|
* -lglfw3 -framework CoreVideo -framework OpenGL -framework IOKit -framework Cocoa
|
||||||
* -framework IOKit -framework Cocoa -Wno-deprecated-declarations
|
* -Wno-deprecated-declarations -std=c99 -DGRAPHICS_API_OPENGL_33
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* LICENSE: zlib/libpng
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
* This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
* BSD-like license that allows static linking with closed source software:
|
* BSD-like license that allows static linking with closed source software:
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2014-2021 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
* will the authors be held liable for any damages arising from the use of this software.
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
|
@ -107,7 +107,7 @@ static void DrawCube(Vector3 position, float width, float height, float length,
|
||||||
static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color);
|
static void DrawCubeWires(Vector3 position, float width, float height, float length, Color color);
|
||||||
static void DrawRectangleV(Vector2 position, Vector2 size, Color color);
|
static void DrawRectangleV(Vector2 position, Vector2 size, Color color);
|
||||||
|
|
||||||
// NOTE: We used raymath to get this functionality but it can be implemented here
|
// NOTE: We use raymath to get this functionality but it could be implemented in this module
|
||||||
//static Matrix MatrixIdentity(void);
|
//static Matrix MatrixIdentity(void);
|
||||||
//static Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far);
|
//static Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far);
|
||||||
//static Matrix MatrixPerspective(double fovy, double aspect, double near, double far);
|
//static Matrix MatrixPerspective(double fovy, double aspect, double near, double far);
|
||||||
|
|
@ -144,7 +144,6 @@ int main(void)
|
||||||
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
|
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL);
|
GLFWwindow *window = glfwCreateWindow(screenWidth, screenHeight, "rlgl standalone", NULL, NULL);
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
|
|
@ -219,8 +218,8 @@ int main(void)
|
||||||
|
|
||||||
// Draw '2D' elements in the scene (GUI)
|
// Draw '2D' elements in the scene (GUI)
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
#define RLGL_CREATE_MATRIX_MANUALLY
|
#define RLGL_SET_MATRIX_MANUALLY
|
||||||
#if defined(RLGL_CREATE_MATRIX_MANUALLY)
|
#if defined(RLGL_SET_MATRIX_MANUALLY)
|
||||||
matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0);
|
matProj = MatrixOrtho(0.0, screenWidth, screenHeight, 0.0, 0.0, 1.0);
|
||||||
matView = MatrixIdentity();
|
matView = MatrixIdentity();
|
||||||
|
|
||||||
|
|
@ -237,7 +236,7 @@ int main(void)
|
||||||
#endif
|
#endif
|
||||||
DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY);
|
DrawRectangleV((Vector2){ 10.0f, 10.0f }, (Vector2){ 780.0f, 20.0f }, DARKGRAY);
|
||||||
|
|
||||||
// Draw internal render batch buffers (3D data)
|
// Draw internal render batch buffers (2D data)
|
||||||
rlDrawRenderBatchActive();
|
rlDrawRenderBatchActive();
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
#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 DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection
|
||||||
|
|
||||||
|
// Main entry point
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
@ -119,4 +123,144 @@ tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet ris
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Module functions definition
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw text using font inside rectangle limits
|
||||||
|
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
|
||||||
|
{
|
||||||
|
DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text using font inside rectangle limits with support for text selection
|
||||||
|
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint)
|
||||||
|
{
|
||||||
|
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||||
|
|
||||||
|
float textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||||
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||||
|
|
||||||
|
float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor
|
||||||
|
|
||||||
|
// Word/character wrapping mechanism variables
|
||||||
|
enum { MEASURE_STATE = 0, DRAW_STATE = 1 };
|
||||||
|
int state = wordWrap? MEASURE_STATE : DRAW_STATE;
|
||||||
|
|
||||||
|
int startLine = -1; // Index where to begin drawing (where a line begins)
|
||||||
|
int endLine = -1; // Index where to stop drawing (where a line ends)
|
||||||
|
int lastk = -1; // Holds last value of the character position
|
||||||
|
|
||||||
|
for (int i = 0, k = 0; i < length; i++, k++)
|
||||||
|
{
|
||||||
|
// Get next codepoint from byte string and glyph index in font
|
||||||
|
int codepointByteCount = 0;
|
||||||
|
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
|
||||||
|
int index = GetGlyphIndex(font, codepoint);
|
||||||
|
|
||||||
|
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||||
|
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||||
|
if (codepoint == 0x3f) codepointByteCount = 1;
|
||||||
|
i += (codepointByteCount - 1);
|
||||||
|
|
||||||
|
float glyphWidth = 0;
|
||||||
|
if (codepoint != '\n')
|
||||||
|
{
|
||||||
|
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
|
||||||
|
|
||||||
|
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
||||||
|
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
||||||
|
// and change states again and again recursively until the end of the text (or until we get outside of the container).
|
||||||
|
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
||||||
|
// and begin drawing on the next line before we can get outside the container.
|
||||||
|
if (state == MEASURE_STATE)
|
||||||
|
{
|
||||||
|
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
||||||
|
// Ref: http://jkorpela.fi/chars/spaces.html
|
||||||
|
if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i;
|
||||||
|
|
||||||
|
if ((textOffsetX + glyphWidth) > rec.width)
|
||||||
|
{
|
||||||
|
endLine = (endLine < 1)? i : endLine;
|
||||||
|
if (i == endLine) endLine -= codepointByteCount;
|
||||||
|
if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount);
|
||||||
|
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
else if ((i + 1) == length)
|
||||||
|
{
|
||||||
|
endLine = i;
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
else if (codepoint == '\n') state = !state;
|
||||||
|
|
||||||
|
if (state == DRAW_STATE)
|
||||||
|
{
|
||||||
|
textOffsetX = 0;
|
||||||
|
i = startLine;
|
||||||
|
glyphWidth = 0;
|
||||||
|
|
||||||
|
// Save character position when we switch states
|
||||||
|
int tmp = lastk;
|
||||||
|
lastk = k - 1;
|
||||||
|
k = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (codepoint == '\n')
|
||||||
|
{
|
||||||
|
if (!wordWrap)
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When text overflows rectangle height limit, just stop drawing
|
||||||
|
if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break;
|
||||||
|
|
||||||
|
// Draw selection background
|
||||||
|
bool isGlyphSelected = false;
|
||||||
|
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
|
||||||
|
{
|
||||||
|
DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint);
|
||||||
|
isGlyphSelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw current character glyph
|
||||||
|
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||||
|
{
|
||||||
|
DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wordWrap && (i == endLine))
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
startLine = endLine;
|
||||||
|
endLine = -1;
|
||||||
|
glyphWidth = 0;
|
||||||
|
selectStart += lastk - k;
|
||||||
|
k = lastk;
|
||||||
|
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textOffsetX += glyphWidth;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -133,6 +133,9 @@ 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 DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
// Global variables
|
// Global variables
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
@ -145,6 +148,9 @@ struct {
|
||||||
|
|
||||||
static int hovered = -1, selected = -1;
|
static int hovered = -1, selected = -1;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Main entry point
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
@ -317,3 +323,143 @@ static void RandomizeEmoji(void)
|
||||||
emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1);
|
emoji[i].message = GetRandomValue(0, SIZEOF(messages) - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Module functions definition
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw text using font inside rectangle limits
|
||||||
|
static void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
|
||||||
|
{
|
||||||
|
DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text using font inside rectangle limits with support for text selection
|
||||||
|
static void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint)
|
||||||
|
{
|
||||||
|
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
||||||
|
|
||||||
|
float textOffsetY = 0; // Offset between lines (on line break '\n')
|
||||||
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
||||||
|
|
||||||
|
float scaleFactor = fontSize/(float)font.baseSize; // Character rectangle scaling factor
|
||||||
|
|
||||||
|
// Word/character wrapping mechanism variables
|
||||||
|
enum { MEASURE_STATE = 0, DRAW_STATE = 1 };
|
||||||
|
int state = wordWrap? MEASURE_STATE : DRAW_STATE;
|
||||||
|
|
||||||
|
int startLine = -1; // Index where to begin drawing (where a line begins)
|
||||||
|
int endLine = -1; // Index where to stop drawing (where a line ends)
|
||||||
|
int lastk = -1; // Holds last value of the character position
|
||||||
|
|
||||||
|
for (int i = 0, k = 0; i < length; i++, k++)
|
||||||
|
{
|
||||||
|
// Get next codepoint from byte string and glyph index in font
|
||||||
|
int codepointByteCount = 0;
|
||||||
|
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
|
||||||
|
int index = GetGlyphIndex(font, codepoint);
|
||||||
|
|
||||||
|
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
||||||
|
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
||||||
|
if (codepoint == 0x3f) codepointByteCount = 1;
|
||||||
|
i += (codepointByteCount - 1);
|
||||||
|
|
||||||
|
float glyphWidth = 0;
|
||||||
|
if (codepoint != '\n')
|
||||||
|
{
|
||||||
|
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
|
||||||
|
|
||||||
|
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
||||||
|
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
||||||
|
// and change states again and again recursively until the end of the text (or until we get outside of the container).
|
||||||
|
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
||||||
|
// and begin drawing on the next line before we can get outside the container.
|
||||||
|
if (state == MEASURE_STATE)
|
||||||
|
{
|
||||||
|
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
||||||
|
// Ref: http://jkorpela.fi/chars/spaces.html
|
||||||
|
if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i;
|
||||||
|
|
||||||
|
if ((textOffsetX + glyphWidth) > rec.width)
|
||||||
|
{
|
||||||
|
endLine = (endLine < 1)? i : endLine;
|
||||||
|
if (i == endLine) endLine -= codepointByteCount;
|
||||||
|
if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount);
|
||||||
|
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
else if ((i + 1) == length)
|
||||||
|
{
|
||||||
|
endLine = i;
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
else if (codepoint == '\n') state = !state;
|
||||||
|
|
||||||
|
if (state == DRAW_STATE)
|
||||||
|
{
|
||||||
|
textOffsetX = 0;
|
||||||
|
i = startLine;
|
||||||
|
glyphWidth = 0;
|
||||||
|
|
||||||
|
// Save character position when we switch states
|
||||||
|
int tmp = lastk;
|
||||||
|
lastk = k - 1;
|
||||||
|
k = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (codepoint == '\n')
|
||||||
|
{
|
||||||
|
if (!wordWrap)
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When text overflows rectangle height limit, just stop drawing
|
||||||
|
if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break;
|
||||||
|
|
||||||
|
// Draw selection background
|
||||||
|
bool isGlyphSelected = false;
|
||||||
|
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
|
||||||
|
{
|
||||||
|
DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint);
|
||||||
|
isGlyphSelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw current character glyph
|
||||||
|
if ((codepoint != ' ') && (codepoint != '\t'))
|
||||||
|
{
|
||||||
|
DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wordWrap && (i == endLine))
|
||||||
|
{
|
||||||
|
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
||||||
|
textOffsetX = 0;
|
||||||
|
startLine = endLine;
|
||||||
|
endLine = -1;
|
||||||
|
glyphWidth = 0;
|
||||||
|
selectStart += lastk - k;
|
||||||
|
k = lastk;
|
||||||
|
|
||||||
|
state = !state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textOffsetX += glyphWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -94,10 +94,6 @@
|
||||||
} CameraProjection;
|
} CameraProjection;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -106,6 +102,11 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(CAMERA_STANDALONE)
|
||||||
void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
||||||
void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
||||||
|
|
|
||||||
162
src/external/par_shapes.h
vendored
162
src/external/par_shapes.h
vendored
|
|
@ -21,8 +21,7 @@
|
||||||
// coordinates (one per vertex). That's it! If you need something fancier,
|
// coordinates (one per vertex). That's it! If you need something fancier,
|
||||||
// look elsewhere.
|
// look elsewhere.
|
||||||
//
|
//
|
||||||
// The MIT License
|
// Distributed under the MIT License, see bottom of file.
|
||||||
// Copyright (c) 2015 Philip Rideout
|
|
||||||
|
|
||||||
#ifndef PAR_SHAPES_H
|
#ifndef PAR_SHAPES_H
|
||||||
#define PAR_SHAPES_H
|
#define PAR_SHAPES_H
|
||||||
|
|
@ -32,8 +31,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
// Ray (@raysan5): Commented to avoid conflict with raylib bool
|
||||||
// Ray: commented to avoid conflict with raylib bool
|
|
||||||
/*
|
/*
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
|
|
@ -41,9 +39,9 @@ extern "C" {
|
||||||
# if _MSC_VER >= 1800
|
# if _MSC_VER >= 1800
|
||||||
# include <stdbool.h>
|
# include <stdbool.h>
|
||||||
# else // stdbool.h missing prior to MSVC++ 12.0 (VS2013)
|
# else // stdbool.h missing prior to MSVC++ 12.0 (VS2013)
|
||||||
//# define bool int
|
# define bool int
|
||||||
//# define true 1
|
# define true 1
|
||||||
//# define false 0
|
# define false 0
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,6 +69,14 @@ void par_shapes_free_mesh(par_shapes_mesh*);
|
||||||
// both 1.0, but they can easily be changed with par_shapes_scale.
|
// both 1.0, but they can easily be changed with par_shapes_scale.
|
||||||
par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks);
|
par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks);
|
||||||
|
|
||||||
|
// Cone is similar to cylinder but the radius diminishes to zero as Z increases.
|
||||||
|
// Again, height and radius are 1.0, but can be changed with par_shapes_scale.
|
||||||
|
par_shapes_mesh* par_shapes_create_cone(int slices, int stacks);
|
||||||
|
|
||||||
|
// Create a disk of radius 1.0 with texture coordinates and normals by squashing
|
||||||
|
// a cone flat on the Z=0 plane.
|
||||||
|
par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks);
|
||||||
|
|
||||||
// Create a donut that sits on the Z=0 plane with the specified inner radius.
|
// Create a donut that sits on the Z=0 plane with the specified inner radius.
|
||||||
// The outer radius can be controlled with par_shapes_scale.
|
// The outer radius can be controlled with par_shapes_scale.
|
||||||
par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius);
|
par_shapes_mesh* par_shapes_create_torus(int slices, int stacks, float radius);
|
||||||
|
|
@ -172,6 +178,17 @@ par_shapes_mesh* par_shapes_weld(par_shapes_mesh const*, float epsilon,
|
||||||
// Compute smooth normals by averaging adjacent facet normals.
|
// Compute smooth normals by averaging adjacent facet normals.
|
||||||
void par_shapes_compute_normals(par_shapes_mesh* m);
|
void par_shapes_compute_normals(par_shapes_mesh* m);
|
||||||
|
|
||||||
|
// Global Config ---------------------------------------------------------------
|
||||||
|
|
||||||
|
void par_shapes_set_epsilon_welded_normals(float epsilon);
|
||||||
|
void par_shapes_set_epsilon_degenerate_sphere(float epsilon);
|
||||||
|
|
||||||
|
// Advanced --------------------------------------------------------------------
|
||||||
|
|
||||||
|
void par_shapes__compute_welded_normals(par_shapes_mesh* m);
|
||||||
|
void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder,
|
||||||
|
int slices);
|
||||||
|
|
||||||
#ifndef PAR_PI
|
#ifndef PAR_PI
|
||||||
#define PAR_PI (3.14159265359)
|
#define PAR_PI (3.14159265359)
|
||||||
#define PAR_MIN(a, b) (a > b ? b : a)
|
#define PAR_MIN(a, b) (a > b ? b : a)
|
||||||
|
|
@ -205,11 +222,15 @@ void par_shapes_compute_normals(par_shapes_mesh* m);
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
static float par_shapes__epsilon_welded_normals = 0.001;
|
||||||
|
static float par_shapes__epsilon_degenerate_sphere = 0.0001;
|
||||||
|
|
||||||
static void par_shapes__sphere(float const* uv, float* xyz, void*);
|
static void par_shapes__sphere(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__hemisphere(float const* uv, float* xyz, void*);
|
static void par_shapes__hemisphere(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__plane(float const* uv, float* xyz, void*);
|
static void par_shapes__plane(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__klein(float const* uv, float* xyz, void*);
|
static void par_shapes__klein(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__cylinder(float const* uv, float* xyz, void*);
|
static void par_shapes__cylinder(float const* uv, float* xyz, void*);
|
||||||
|
static void par_shapes__cone(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__torus(float const* uv, float* xyz, void*);
|
static void par_shapes__torus(float const* uv, float* xyz, void*);
|
||||||
static void par_shapes__trefoil(float const* uv, float* xyz, void*);
|
static void par_shapes__trefoil(float const* uv, float* xyz, void*);
|
||||||
|
|
||||||
|
|
@ -298,11 +319,12 @@ static float par_shapes__sqrdist3(float const* a, float const* b)
|
||||||
return dx * dx + dy * dy + dz * dz;
|
return dx * dx + dy * dy + dz * dz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void par_shapes__compute_welded_normals(par_shapes_mesh* m)
|
void par_shapes__compute_welded_normals(par_shapes_mesh* m)
|
||||||
{
|
{
|
||||||
|
const float epsilon = par_shapes__epsilon_welded_normals;
|
||||||
m->normals = PAR_MALLOC(float, m->npoints * 3);
|
m->normals = PAR_MALLOC(float, m->npoints * 3);
|
||||||
PAR_SHAPES_T* weldmap = PAR_MALLOC(PAR_SHAPES_T, m->npoints);
|
PAR_SHAPES_T* weldmap = PAR_MALLOC(PAR_SHAPES_T, m->npoints);
|
||||||
par_shapes_mesh* welded = par_shapes_weld(m, 0.01, weldmap);
|
par_shapes_mesh* welded = par_shapes_weld(m, epsilon, weldmap);
|
||||||
par_shapes_compute_normals(welded);
|
par_shapes_compute_normals(welded);
|
||||||
float* pdst = m->normals;
|
float* pdst = m->normals;
|
||||||
for (int i = 0; i < m->npoints; i++, pdst += 3) {
|
for (int i = 0; i < m->npoints; i++, pdst += 3) {
|
||||||
|
|
@ -325,6 +347,24 @@ par_shapes_mesh* par_shapes_create_cylinder(int slices, int stacks)
|
||||||
stacks, 0);
|
stacks, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
par_shapes_mesh* par_shapes_create_cone(int slices, int stacks)
|
||||||
|
{
|
||||||
|
if (slices < 3 || stacks < 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return par_shapes_create_parametric(par_shapes__cone, slices,
|
||||||
|
stacks, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
par_shapes_mesh* par_shapes_create_parametric_disk(int slices, int stacks)
|
||||||
|
{
|
||||||
|
par_shapes_mesh* m = par_shapes_create_cone(slices, stacks);
|
||||||
|
if (m) {
|
||||||
|
par_shapes_scale(m, 1.0f, 1.0f, 0.0f);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks)
|
par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks)
|
||||||
{
|
{
|
||||||
if (slices < 3 || stacks < 3) {
|
if (slices < 3 || stacks < 3) {
|
||||||
|
|
@ -332,7 +372,7 @@ par_shapes_mesh* par_shapes_create_parametric_sphere(int slices, int stacks)
|
||||||
}
|
}
|
||||||
par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__sphere,
|
par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__sphere,
|
||||||
slices, stacks, 0);
|
slices, stacks, 0);
|
||||||
par_shapes_remove_degenerate(m, 0.0001);
|
par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,7 +383,7 @@ par_shapes_mesh* par_shapes_create_hemisphere(int slices, int stacks)
|
||||||
}
|
}
|
||||||
par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__hemisphere,
|
par_shapes_mesh* m = par_shapes_create_parametric(par_shapes__hemisphere,
|
||||||
slices, stacks, 0);
|
slices, stacks, 0);
|
||||||
par_shapes_remove_degenerate(m, 0.0001);
|
par_shapes_remove_degenerate(m, par_shapes__epsilon_degenerate_sphere);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -579,6 +619,15 @@ static void par_shapes__cylinder(float const* uv, float* xyz, void* userdata)
|
||||||
xyz[2] = uv[0];
|
xyz[2] = uv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void par_shapes__cone(float const* uv, float* xyz, void* userdata)
|
||||||
|
{
|
||||||
|
float r = 1.0f - uv[0];
|
||||||
|
float theta = uv[1] * 2 * PAR_PI;
|
||||||
|
xyz[0] = r * sinf(theta);
|
||||||
|
xyz[1] = r * cosf(theta);
|
||||||
|
xyz[2] = uv[0];
|
||||||
|
}
|
||||||
|
|
||||||
static void par_shapes__torus(float const* uv, float* xyz, void* userdata)
|
static void par_shapes__torus(float const* uv, float* xyz, void* userdata)
|
||||||
{
|
{
|
||||||
float major = 1;
|
float major = 1;
|
||||||
|
|
@ -620,6 +669,14 @@ static void par_shapes__trefoil(float const* uv, float* xyz, void* userdata)
|
||||||
xyz[2] = z + d * ww[2] * sin(v);
|
xyz[2] = z + d * ww[2] * sin(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void par_shapes_set_epsilon_welded_normals(float epsilon) {
|
||||||
|
par_shapes__epsilon_welded_normals = epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void par_shapes_set_epsilon_degenerate_sphere(float epsilon) {
|
||||||
|
par_shapes__epsilon_degenerate_sphere = epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src)
|
void par_shapes_merge(par_shapes_mesh* dst, par_shapes_mesh const* src)
|
||||||
{
|
{
|
||||||
PAR_SHAPES_T offset = dst->npoints;
|
PAR_SHAPES_T offset = dst->npoints;
|
||||||
|
|
@ -744,15 +801,15 @@ void par_shapes_rotate(par_shapes_mesh* mesh, float radians, float const* axis)
|
||||||
p[1] = y;
|
p[1] = y;
|
||||||
p[2] = z;
|
p[2] = z;
|
||||||
}
|
}
|
||||||
p = mesh->normals;
|
float* n = mesh->normals;
|
||||||
if (p) {
|
if (n) {
|
||||||
for (int i = 0; i < mesh->npoints; i++, p += 3) {
|
for (int i = 0; i < mesh->npoints; i++, n += 3) {
|
||||||
float x = col0[0] * p[0] + col1[0] * p[1] + col2[0] * p[2];
|
float x = col0[0] * n[0] + col1[0] * n[1] + col2[0] * n[2];
|
||||||
float y = col0[1] * p[0] + col1[1] * p[1] + col2[1] * p[2];
|
float y = col0[1] * n[0] + col1[1] * n[1] + col2[1] * n[2];
|
||||||
float z = col0[2] * p[0] + col1[2] * p[1] + col2[2] * p[2];
|
float z = col0[2] * n[0] + col1[2] * n[1] + col2[2] * n[2];
|
||||||
p[0] = x;
|
n[0] = x;
|
||||||
p[1] = y;
|
n[1] = y;
|
||||||
p[2] = z;
|
n[2] = z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -765,6 +822,27 @@ void par_shapes_scale(par_shapes_mesh* m, float x, float y, float z)
|
||||||
*points++ *= y;
|
*points++ *= y;
|
||||||
*points++ *= z;
|
*points++ *= z;
|
||||||
}
|
}
|
||||||
|
float* n = m->normals;
|
||||||
|
if (n && !(x == y && y == z)) {
|
||||||
|
bool x_zero = x == 0;
|
||||||
|
bool y_zero = y == 0;
|
||||||
|
bool z_zero = z == 0;
|
||||||
|
if (!x_zero && !y_zero && !z_zero) {
|
||||||
|
x = 1.0f / x;
|
||||||
|
y = 1.0f / y;
|
||||||
|
z = 1.0f / z;
|
||||||
|
} else {
|
||||||
|
x = x_zero && !y_zero && !z_zero;
|
||||||
|
y = y_zero && !x_zero && !z_zero;
|
||||||
|
z = z_zero && !x_zero && !y_zero;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < m->npoints; i++, n += 3) {
|
||||||
|
n[0] *= x;
|
||||||
|
n[1] *= y;
|
||||||
|
n[2] *= z;
|
||||||
|
par_shapes__normalize3(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src)
|
void par_shapes_merge_and_free(par_shapes_mesh* dst, par_shapes_mesh* src)
|
||||||
|
|
@ -1098,8 +1176,8 @@ static par_shapes_mesh* par_shapes__apply_turtle(par_shapes_mesh* mesh,
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void par_shapes__connect(par_shapes_mesh* scene,
|
void par_shapes__connect(par_shapes_mesh* scene, par_shapes_mesh* cylinder,
|
||||||
par_shapes_mesh* cylinder, int slices)
|
int slices)
|
||||||
{
|
{
|
||||||
int stacks = 1;
|
int stacks = 1;
|
||||||
int npoints = (slices + 1) * (stacks + 1);
|
int npoints = (slices + 1) * (stacks + 1);
|
||||||
|
|
@ -1118,7 +1196,8 @@ static void par_shapes__connect(par_shapes_mesh* scene,
|
||||||
// Create the new triangle list.
|
// Create the new triangle list.
|
||||||
int ntriangles = scene->ntriangles + 2 * slices * stacks;
|
int ntriangles = scene->ntriangles + 2 * slices * stacks;
|
||||||
PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, ntriangles * 3);
|
PAR_SHAPES_T* triangles = PAR_MALLOC(PAR_SHAPES_T, ntriangles * 3);
|
||||||
memcpy(triangles, scene->triangles, 2 * scene->ntriangles * 3);
|
memcpy(triangles, scene->triangles,
|
||||||
|
sizeof(PAR_SHAPES_T) * scene->ntriangles * 3);
|
||||||
int v = scene->npoints - (slices + 1);
|
int v = scene->npoints - (slices + 1);
|
||||||
PAR_SHAPES_T* face = triangles + scene->ntriangles * 3;
|
PAR_SHAPES_T* face = triangles + scene->ntriangles * 3;
|
||||||
for (int stack = 0; stack < stacks; stack++) {
|
for (int stack = 0; stack < stacks; stack++) {
|
||||||
|
|
@ -1154,7 +1233,7 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices,
|
||||||
while (cmd) {
|
while (cmd) {
|
||||||
char *arg = strtok(0, " ");
|
char *arg = strtok(0, " ");
|
||||||
if (!arg) {
|
if (!arg) {
|
||||||
//puts("lsystem error: unexpected end of program.");
|
puts("lsystem error: unexpected end of program.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!strcmp(cmd, "rule")) {
|
if (!strcmp(cmd, "rule")) {
|
||||||
|
|
@ -1208,7 +1287,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices,
|
||||||
|
|
||||||
// For testing purposes, dump out the parsed program.
|
// For testing purposes, dump out the parsed program.
|
||||||
#ifdef TEST_PARSE
|
#ifdef TEST_PARSE
|
||||||
/*
|
|
||||||
for (int i = 0; i < nrules; i++) {
|
for (int i = 0; i < nrules; i++) {
|
||||||
par_shapes__rule rule = rules[i];
|
par_shapes__rule rule = rules[i];
|
||||||
printf("rule %s.%d\n", rule.name, rule.weight);
|
printf("rule %s.%d\n", rule.name, rule.weight);
|
||||||
|
|
@ -1217,7 +1295,6 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices,
|
||||||
printf("\t%s %s\n", cmd.cmd, cmd.arg);
|
printf("\t%s %s\n", cmd.cmd, cmd.arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Instantiate the aggregated shape and the template shapes.
|
// Instantiate the aggregated shape and the template shapes.
|
||||||
|
|
@ -1258,7 +1335,8 @@ par_shapes_mesh* par_shapes_create_lsystem(char const* text, int slices,
|
||||||
|
|
||||||
par_shapes__command* cmd = rule->commands + (frame->pc++);
|
par_shapes__command* cmd = rule->commands + (frame->pc++);
|
||||||
#ifdef DUMP_TRACE
|
#ifdef DUMP_TRACE
|
||||||
//printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name, frame->pc - 1, stackptr);
|
printf("%5s %5s %5s:%d %03d\n", cmd->cmd, cmd->arg, rule->name,
|
||||||
|
frame->pc - 1, stackptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float value;
|
float value;
|
||||||
|
|
@ -1620,7 +1698,7 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize,
|
||||||
PAR_SHAPES_T binvalue = *(bins + binindex);
|
PAR_SHAPES_T binvalue = *(bins + binindex);
|
||||||
if (binvalue > 0) {
|
if (binvalue > 0) {
|
||||||
if (nbins == 8) {
|
if (nbins == 8) {
|
||||||
//printf("Epsilon value is too large.\n");
|
printf("Epsilon value is too large.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nearby[nbins++] = binindex;
|
nearby[nbins++] = binindex;
|
||||||
|
|
@ -1632,8 +1710,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize,
|
||||||
// Check for colocated points in each nearby bin.
|
// Check for colocated points in each nearby bin.
|
||||||
for (int b = 0; b < nbins; b++) {
|
for (int b = 0; b < nbins; b++) {
|
||||||
int binindex = nearby[b];
|
int binindex = nearby[b];
|
||||||
PAR_SHAPES_T binvalue = *(bins + binindex);
|
PAR_SHAPES_T binvalue = bins[binindex];
|
||||||
PAR_SHAPES_T nindex = binvalue - 1;
|
PAR_SHAPES_T nindex = binvalue - 1;
|
||||||
|
assert(nindex < mesh->npoints);
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
// If this isn't "self" and it's colocated, then weld it!
|
// If this isn't "self" and it's colocated, then weld it!
|
||||||
|
|
@ -1699,6 +1778,9 @@ static void par_shapes__weld_points(par_shapes_mesh* mesh, int gridsize,
|
||||||
PAR_SHAPES_T b = weldmap[tsrc[1]];
|
PAR_SHAPES_T b = weldmap[tsrc[1]];
|
||||||
PAR_SHAPES_T c = weldmap[tsrc[2]];
|
PAR_SHAPES_T c = weldmap[tsrc[2]];
|
||||||
if (a != b && a != c && b != c) {
|
if (a != b && a != c && b != c) {
|
||||||
|
assert(a < mesh->npoints);
|
||||||
|
assert(b < mesh->npoints);
|
||||||
|
assert(c < mesh->npoints);
|
||||||
*tdst++ = a;
|
*tdst++ = a;
|
||||||
*tdst++ = b;
|
*tdst++ = b;
|
||||||
*tdst++ = c;
|
*tdst++ = c;
|
||||||
|
|
@ -2049,3 +2131,25 @@ void par_shapes_remove_degenerate(par_shapes_mesh* mesh, float mintriarea)
|
||||||
|
|
||||||
#endif // PAR_SHAPES_IMPLEMENTATION
|
#endif // PAR_SHAPES_IMPLEMENTATION
|
||||||
#endif // PAR_SHAPES_H
|
#endif // PAR_SHAPES_H
|
||||||
|
|
||||||
|
// par_shapes is distributed under the MIT license:
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Philip Rideout
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,9 @@
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define PHYSAC_STATIC (defined by default)
|
|
||||||
* The generated implementation will stay private inside implementation file and all
|
|
||||||
* internal symbols and functions will only be visible inside that file.
|
|
||||||
*
|
|
||||||
* #define PHYSAC_DEBUG
|
* #define PHYSAC_DEBUG
|
||||||
* Show debug traces log messages about physic bodies creation/destruction, physic system errors,
|
* Show debug traces log messages about physic bodies creation/destruction, physic system errors,
|
||||||
* some calculations results and NULL reference exceptions
|
* some calculations results and NULL reference exceptions.
|
||||||
*
|
|
||||||
* #define PHYSAC_DEFINE_VECTOR2_TYPE
|
|
||||||
* Forces library to define struct Vector2 data type (float x; float y)
|
|
||||||
*
|
*
|
||||||
* #define PHYSAC_AVOID_TIMMING_SYSTEM
|
* #define PHYSAC_AVOID_TIMMING_SYSTEM
|
||||||
* Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
|
* Disables internal timming system, used by UpdatePhysics() to launch timmed physic steps,
|
||||||
|
|
@ -79,14 +72,8 @@
|
||||||
#if !defined(PHYSAC_H)
|
#if !defined(PHYSAC_H)
|
||||||
#define PHYSAC_H
|
#define PHYSAC_H
|
||||||
|
|
||||||
#if defined(PHYSAC_STATIC)
|
#ifndef PHYSACDEF
|
||||||
#define PHYSACDEF static // Functions just visible to module including this file
|
#define PHYSACDEF // We are building or using physac as a static library
|
||||||
#else
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
#define PHYSACDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
|
||||||
#else
|
|
||||||
#define PHYSACDEF extern // Functions visible from other files
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Allow custom memory allocators
|
// Allow custom memory allocators
|
||||||
|
|
@ -127,7 +114,7 @@ typedef enum PhysicsShapeType { PHYSICS_CIRCLE = 0, PHYSICS_POLYGON } PhysicsSha
|
||||||
// Previously defined to be used in PhysicsShape struct as circular dependencies
|
// Previously defined to be used in PhysicsShape struct as circular dependencies
|
||||||
typedef struct PhysicsBodyData *PhysicsBody;
|
typedef struct PhysicsBodyData *PhysicsBody;
|
||||||
|
|
||||||
#if defined(PHYSAC_DEFINE_VECTOR2_TYPE)
|
#if !defined(RL_VECTOR2_TYPE)
|
||||||
// Vector2 type
|
// Vector2 type
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
float x;
|
float x;
|
||||||
|
|
@ -192,13 +179,13 @@ typedef struct PhysicsManifoldData {
|
||||||
float staticFriction; // Mixed static friction during collision
|
float staticFriction; // Mixed static friction during collision
|
||||||
} PhysicsManifoldData, *PhysicsManifold;
|
} PhysicsManifoldData, *PhysicsManifold;
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Physics system management
|
// Physics system management
|
||||||
PHYSACDEF void InitPhysics(void); // Initializes physics system
|
PHYSACDEF void InitPhysics(void); // Initializes physics system
|
||||||
PHYSACDEF void UpdatePhysics(void); // Update physics system
|
PHYSACDEF void UpdatePhysics(void); // Update physics system
|
||||||
|
|
@ -225,7 +212,6 @@ PHYSACDEF int GetPhysicsBodiesCount(void);
|
||||||
PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
PHYSACDEF int GetPhysicsShapeType(int index); // Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
||||||
PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
|
PHYSACDEF int GetPhysicsShapeVerticesCount(int index); // Returns the amount of vertices of a physics body shape
|
||||||
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
|
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex); // Returns transformed position of a body shape (body position + vertex transformed position)
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -253,11 +239,17 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex);
|
||||||
|
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
// Time management functionality
|
// Time management functionality
|
||||||
#include <time.h> // Required for: time(), clock_gettime()
|
#include <time.h> // Required for: time(), clock_gettime()
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Functions required to query time on Windows
|
// Functions required to query time on Windows
|
||||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__) || defined(__FreeBSD__)
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
#if _POSIX_C_SOURCE < 199309L
|
#if _POSIX_C_SOURCE < 199309L
|
||||||
|
|
@ -366,7 +358,7 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initializes physics values, pointers and creates physics loop thread
|
// Initializes physics values, pointers and creates physics loop thread
|
||||||
PHYSACDEF void InitPhysics(void)
|
void InitPhysics(void)
|
||||||
{
|
{
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
// Initialize high resolution timer
|
// Initialize high resolution timer
|
||||||
|
|
@ -377,21 +369,21 @@ PHYSACDEF void InitPhysics(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets physics global gravity force
|
// Sets physics global gravity force
|
||||||
PHYSACDEF void SetPhysicsGravity(float x, float y)
|
void SetPhysicsGravity(float x, float y)
|
||||||
{
|
{
|
||||||
gravityForce.x = x;
|
gravityForce.x = x;
|
||||||
gravityForce.y = y;
|
gravityForce.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new circle physics body with generic parameters
|
// Creates a new circle physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
|
PhysicsBody CreatePhysicsBodyCircle(Vector2 pos, float radius, float density)
|
||||||
{
|
{
|
||||||
PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
|
PhysicsBody body = CreatePhysicsBodyPolygon(pos, radius, PHYSAC_DEFAULT_CIRCLE_VERTICES, density);
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new rectangle physics body with generic parameters
|
// Creates a new rectangle physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
|
PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float height, float density)
|
||||||
{
|
{
|
||||||
// NOTE: Make sure body data is initialized to 0
|
// NOTE: Make sure body data is initialized to 0
|
||||||
PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
|
PhysicsBody body = (PhysicsBody)PHYSAC_CALLOC(sizeof(PhysicsBodyData), 1);
|
||||||
|
|
@ -469,7 +461,7 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyRectangle(Vector2 pos, float width, float
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new polygon physics body with generic parameters
|
// Creates a new polygon physics body with generic parameters
|
||||||
PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
|
PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int sides, float density)
|
||||||
{
|
{
|
||||||
PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
|
PhysicsBody body = (PhysicsBody)PHYSAC_MALLOC(sizeof(PhysicsBodyData));
|
||||||
usedMemory += sizeof(PhysicsBodyData);
|
usedMemory += sizeof(PhysicsBodyData);
|
||||||
|
|
@ -551,19 +543,19 @@ PHYSACDEF PhysicsBody CreatePhysicsBodyPolygon(Vector2 pos, float radius, int si
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a force to a physics body
|
// Adds a force to a physics body
|
||||||
PHYSACDEF void PhysicsAddForce(PhysicsBody body, Vector2 force)
|
void PhysicsAddForce(PhysicsBody body, Vector2 force)
|
||||||
{
|
{
|
||||||
if (body != NULL) body->force = MathVector2Add(body->force, force);
|
if (body != NULL) body->force = MathVector2Add(body->force, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds an angular force to a physics body
|
// Adds an angular force to a physics body
|
||||||
PHYSACDEF void PhysicsAddTorque(PhysicsBody body, float amount)
|
void PhysicsAddTorque(PhysicsBody body, float amount)
|
||||||
{
|
{
|
||||||
if (body != NULL) body->torque += amount;
|
if (body != NULL) body->torque += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shatters a polygon shape physics body to little physics bodies with explosion force
|
// Shatters a polygon shape physics body to little physics bodies with explosion force
|
||||||
PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -700,13 +692,13 @@ PHYSACDEF void PhysicsShatter(PhysicsBody body, Vector2 position, float force)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current amount of created physics bodies
|
// Returns the current amount of created physics bodies
|
||||||
PHYSACDEF int GetPhysicsBodiesCount(void)
|
int GetPhysicsBodiesCount(void)
|
||||||
{
|
{
|
||||||
return physicsBodiesCount;
|
return physicsBodiesCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a physics body of the bodies pool at a specific index
|
// Returns a physics body of the bodies pool at a specific index
|
||||||
PHYSACDEF PhysicsBody GetPhysicsBody(int index)
|
PhysicsBody GetPhysicsBody(int index)
|
||||||
{
|
{
|
||||||
PhysicsBody body = NULL;
|
PhysicsBody body = NULL;
|
||||||
|
|
||||||
|
|
@ -722,7 +714,7 @@ PHYSACDEF PhysicsBody GetPhysicsBody(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
// Returns the physics body shape type (PHYSICS_CIRCLE or PHYSICS_POLYGON)
|
||||||
PHYSACDEF int GetPhysicsShapeType(int index)
|
int GetPhysicsShapeType(int index)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|
||||||
|
|
@ -739,7 +731,7 @@ PHYSACDEF int GetPhysicsShapeType(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the amount of vertices of a physics body shape
|
// Returns the amount of vertices of a physics body shape
|
||||||
PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
|
int GetPhysicsShapeVerticesCount(int index)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
|
|
@ -764,7 +756,7 @@ PHYSACDEF int GetPhysicsShapeVerticesCount(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns transformed position of a body shape (body position + vertex transformed position)
|
// Returns transformed position of a body shape (body position + vertex transformed position)
|
||||||
PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
||||||
{
|
{
|
||||||
Vector2 position = { 0.0f, 0.0f };
|
Vector2 position = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
|
@ -791,7 +783,7 @@ PHYSACDEF Vector2 GetPhysicsShapeVertex(PhysicsBody body, int vertex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets physics body shape transform based on radians parameter
|
// Sets physics body shape transform based on radians parameter
|
||||||
PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -802,7 +794,7 @@ PHYSACDEF void SetPhysicsBodyRotation(PhysicsBody body, float radians)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unitializes and destroys a physics body
|
// Unitializes and destroys a physics body
|
||||||
PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
|
void DestroyPhysicsBody(PhysicsBody body)
|
||||||
{
|
{
|
||||||
if (body != NULL)
|
if (body != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -844,7 +836,7 @@ PHYSACDEF void DestroyPhysicsBody(PhysicsBody body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroys created physics bodies and manifolds and resets global values
|
// Destroys created physics bodies and manifolds and resets global values
|
||||||
PHYSACDEF void ResetPhysics(void)
|
void ResetPhysics(void)
|
||||||
{
|
{
|
||||||
if (physicsBodiesCount > 0)
|
if (physicsBodiesCount > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -886,7 +878,7 @@ PHYSACDEF void ResetPhysics(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unitializes physics pointers and exits physics loop thread
|
// Unitializes physics pointers and exits physics loop thread
|
||||||
PHYSACDEF void ClosePhysics(void)
|
void ClosePhysics(void)
|
||||||
{
|
{
|
||||||
// Unitialize physics manifolds dynamic memory allocations
|
// Unitialize physics manifolds dynamic memory allocations
|
||||||
if (physicsManifoldsCount > 0)
|
if (physicsManifoldsCount > 0)
|
||||||
|
|
@ -912,91 +904,98 @@ PHYSACDEF void ClosePhysics(void)
|
||||||
else TRACELOG("[PHYSAC] Physics module closed successfully\n");
|
else TRACELOG("[PHYSAC] Physics module closed successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update physics system
|
||||||
|
// Physics steps are launched at a fixed time step if enabled
|
||||||
|
void UpdatePhysics(void)
|
||||||
|
{
|
||||||
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
|
static double deltaTimeAccumulator = 0.0;
|
||||||
|
|
||||||
|
// Calculate current time (ms)
|
||||||
|
currentTime = GetCurrentTime();
|
||||||
|
|
||||||
|
// Calculate current delta time (ms)
|
||||||
|
const double delta = currentTime - startTime;
|
||||||
|
|
||||||
|
// Store the time elapsed since the last frame began
|
||||||
|
deltaTimeAccumulator += delta;
|
||||||
|
|
||||||
|
// Fixed time stepping loop
|
||||||
|
while (deltaTimeAccumulator >= deltaTime)
|
||||||
|
{
|
||||||
|
UpdatePhysicsStep();
|
||||||
|
deltaTimeAccumulator -= deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the starting of this frame
|
||||||
|
startTime = currentTime;
|
||||||
|
#else
|
||||||
|
UpdatePhysicsStep();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPhysicsTimeStep(double delta)
|
||||||
|
{
|
||||||
|
deltaTime = delta;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Internal Functions Definition
|
// Module Internal Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Finds a valid index for a new physics body initialization
|
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
||||||
static int FindAvailableBodyIndex()
|
// Initializes hi-resolution MONOTONIC timer
|
||||||
|
static void InitTimerHiRes(void)
|
||||||
{
|
{
|
||||||
int index = -1;
|
#if defined(_WIN32)
|
||||||
for (int i = 0; i < PHYSAC_MAX_BODIES; i++)
|
QueryPerformanceFrequency((unsigned long long int *) &frequency);
|
||||||
{
|
#endif
|
||||||
int currentId = i;
|
|
||||||
|
|
||||||
// Check if current id already exist in other physics body
|
#if defined(__EMSCRIPTEN__) || defined(__linux__)
|
||||||
for (unsigned int k = 0; k < physicsBodiesCount; k++)
|
struct timespec now;
|
||||||
{
|
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000;
|
||||||
if (bodies[k]->id == currentId)
|
#endif
|
||||||
{
|
|
||||||
currentId++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it is not used, use it as new physics body id
|
#if defined(__APPLE__)
|
||||||
if (currentId == (int)i)
|
mach_timebase_info_data_t timebase;
|
||||||
{
|
mach_timebase_info(&timebase);
|
||||||
index = (int)i;
|
frequency = (timebase.denom*1e9)/timebase.numer;
|
||||||
break;
|
#endif
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
|
||||||
|
startTime = GetCurrentTime(); // Get current time in milliseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a default polygon shape with max vertex distance from polygon pivot
|
// Get hi-res MONOTONIC time measure in clock ticks
|
||||||
static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
|
static unsigned long long int GetClockTicks(void)
|
||||||
{
|
{
|
||||||
PhysicsVertexData data = { 0 };
|
unsigned long long int value = 0;
|
||||||
data.vertexCount = sides;
|
|
||||||
|
|
||||||
// Calculate polygon vertices positions
|
#if defined(_WIN32)
|
||||||
for (unsigned int i = 0; i < data.vertexCount; i++)
|
QueryPerformanceCounter((unsigned long long int *) &value);
|
||||||
{
|
#endif
|
||||||
data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
|
||||||
data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate polygon faces normals
|
#if defined(__linux__)
|
||||||
for (int i = 0; i < (int)data.vertexCount; i++)
|
struct timespec now;
|
||||||
{
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
|
value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec;
|
||||||
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
#endif
|
||||||
|
|
||||||
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
#if defined(__APPLE__)
|
||||||
MathVector2Normalize(&data.normals[i]);
|
value = mach_absolute_time();
|
||||||
}
|
#endif
|
||||||
|
|
||||||
return data;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a rectangle polygon shape based on a min and max positions
|
// Get current time in milliseconds
|
||||||
static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
|
static double GetCurrentTime(void)
|
||||||
{
|
{
|
||||||
PhysicsVertexData data = { 0 };
|
return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
|
||||||
data.vertexCount = 4;
|
|
||||||
|
|
||||||
// Calculate polygon vertices positions
|
|
||||||
data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
|
|
||||||
data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
|
|
||||||
data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
|
|
||||||
data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
|
|
||||||
|
|
||||||
// Calculate polygon faces normals
|
|
||||||
for (unsigned int i = 0; i < data.vertexCount; i++)
|
|
||||||
{
|
|
||||||
int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
|
|
||||||
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
|
||||||
|
|
||||||
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
|
||||||
MathVector2Normalize(&data.normals[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
#endif // !PHYSAC_AVOID_TIMMING_SYSTEM
|
||||||
|
|
||||||
// Update physics step (dynamics, collisions and position corrections)
|
// Update physics step (dynamics, collisions and position corrections)
|
||||||
void UpdatePhysicsStep(void)
|
static void UpdatePhysicsStep(void)
|
||||||
{
|
{
|
||||||
// Clear previous generated collisions information
|
// Clear previous generated collisions information
|
||||||
for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
|
for (int i = (int)physicsManifoldsCount - 1; i >= 0; i--)
|
||||||
|
|
@ -1098,39 +1097,84 @@ void UpdatePhysicsStep(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update physics system
|
// Finds a valid index for a new physics body initialization
|
||||||
// Physics steps are launched at a fixed time step if enabled
|
static int FindAvailableBodyIndex()
|
||||||
PHYSACDEF void UpdatePhysics(void)
|
|
||||||
{
|
{
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
int index = -1;
|
||||||
static double deltaTimeAccumulator = 0.0;
|
for (int i = 0; i < PHYSAC_MAX_BODIES; i++)
|
||||||
|
|
||||||
// Calculate current time (ms)
|
|
||||||
currentTime = GetCurrentTime();
|
|
||||||
|
|
||||||
// Calculate current delta time (ms)
|
|
||||||
const double delta = currentTime - startTime;
|
|
||||||
|
|
||||||
// Store the time elapsed since the last frame began
|
|
||||||
deltaTimeAccumulator += delta;
|
|
||||||
|
|
||||||
// Fixed time stepping loop
|
|
||||||
while (deltaTimeAccumulator >= deltaTime)
|
|
||||||
{
|
{
|
||||||
UpdatePhysicsStep();
|
int currentId = i;
|
||||||
deltaTimeAccumulator -= deltaTime;
|
|
||||||
|
// Check if current id already exist in other physics body
|
||||||
|
for (unsigned int k = 0; k < physicsBodiesCount; k++)
|
||||||
|
{
|
||||||
|
if (bodies[k]->id == currentId)
|
||||||
|
{
|
||||||
|
currentId++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is not used, use it as new physics body id
|
||||||
|
if (currentId == (int)i)
|
||||||
|
{
|
||||||
|
index = (int)i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Record the starting of this frame
|
return index;
|
||||||
startTime = currentTime;
|
|
||||||
#else
|
|
||||||
UpdatePhysicsStep();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PHYSACDEF void SetPhysicsTimeStep(double delta)
|
// Creates a default polygon shape with max vertex distance from polygon pivot
|
||||||
|
static PhysicsVertexData CreateDefaultPolygon(float radius, int sides)
|
||||||
{
|
{
|
||||||
deltaTime = delta;
|
PhysicsVertexData data = { 0 };
|
||||||
|
data.vertexCount = sides;
|
||||||
|
|
||||||
|
// Calculate polygon vertices positions
|
||||||
|
for (unsigned int i = 0; i < data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
data.positions[i].x = (float)cosf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
||||||
|
data.positions[i].y = (float)sinf(360.0f/sides*i*PHYSAC_DEG2RAD)*radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate polygon faces normals
|
||||||
|
for (int i = 0; i < (int)data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
int nextIndex = (((i + 1) < sides) ? (i + 1) : 0);
|
||||||
|
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
||||||
|
|
||||||
|
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
||||||
|
MathVector2Normalize(&data.normals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a rectangle polygon shape based on a min and max positions
|
||||||
|
static PhysicsVertexData CreateRectanglePolygon(Vector2 pos, Vector2 size)
|
||||||
|
{
|
||||||
|
PhysicsVertexData data = { 0 };
|
||||||
|
data.vertexCount = 4;
|
||||||
|
|
||||||
|
// Calculate polygon vertices positions
|
||||||
|
data.positions[0] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y - size.y/2 };
|
||||||
|
data.positions[1] = CLITERAL(Vector2){ pos.x + size.x/2, pos.y + size.y/2 };
|
||||||
|
data.positions[2] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y + size.y/2 };
|
||||||
|
data.positions[3] = CLITERAL(Vector2){ pos.x - size.x/2, pos.y - size.y/2 };
|
||||||
|
|
||||||
|
// Calculate polygon faces normals
|
||||||
|
for (unsigned int i = 0; i < data.vertexCount; i++)
|
||||||
|
{
|
||||||
|
int nextIndex = (((i + 1) < data.vertexCount) ? (i + 1) : 0);
|
||||||
|
Vector2 face = MathVector2Subtract(data.positions[nextIndex], data.positions[i]);
|
||||||
|
|
||||||
|
data.normals[i] = CLITERAL(Vector2){ face.y, -face.x };
|
||||||
|
MathVector2Normalize(&data.normals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds a valid index for a new manifold initialization
|
// Finds a valid index for a new manifold initialization
|
||||||
|
|
@ -1844,59 +1888,6 @@ static Vector2 MathTriangleBarycenter(Vector2 v1, Vector2 v2, Vector2 v3)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(PHYSAC_AVOID_TIMMING_SYSTEM)
|
|
||||||
// Initializes hi-resolution MONOTONIC timer
|
|
||||||
static void InitTimerHiRes(void)
|
|
||||||
{
|
|
||||||
#if defined(_WIN32)
|
|
||||||
QueryPerformanceFrequency((unsigned long long int *) &frequency);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) || defined(__linux__)
|
|
||||||
struct timespec now;
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) frequency = 1000000000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
mach_timebase_info_data_t timebase;
|
|
||||||
mach_timebase_info(&timebase);
|
|
||||||
frequency = (timebase.denom*1e9)/timebase.numer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
baseClockTicks = (double)GetClockTicks(); // Get MONOTONIC clock time offset
|
|
||||||
startTime = GetCurrentTime(); // Get current time in milliseconds
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get hi-res MONOTONIC time measure in clock ticks
|
|
||||||
static unsigned long long int GetClockTicks(void)
|
|
||||||
{
|
|
||||||
unsigned long long int value = 0;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
QueryPerformanceCounter((unsigned long long int *) &value);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
struct timespec now;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
value = (unsigned long long int)now.tv_sec*(unsigned long long int)1000000000 + (unsigned long long int)now.tv_nsec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
value = mach_absolute_time();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get current time in milliseconds
|
|
||||||
static double GetCurrentTime(void)
|
|
||||||
{
|
|
||||||
return (double)(GetClockTicks() - baseClockTicks)/frequency*1000;
|
|
||||||
}
|
|
||||||
#endif // !PHYSAC_AVOID_TIMMING_SYSTEM
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the cross product of a vector and a value
|
// Returns the cross product of a vector and a value
|
||||||
static inline Vector2 MathVector2Product(Vector2 vector, float value)
|
static inline Vector2 MathVector2Product(Vector2 vector, float value)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -99,10 +99,6 @@ typedef struct {
|
||||||
Vector2 position[4];
|
Vector2 position[4];
|
||||||
} GestureEvent;
|
} GestureEvent;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -111,11 +107,15 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(GESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
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 GetTouchPointsCount(void); // Get touch points count
|
||||||
|
|
@ -141,9 +141,15 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
#if defined(GESTURES_IMPLEMENTATION)
|
#if defined(GESTURES_IMPLEMENTATION)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
// Functions required to query time on Windows
|
// Functions required to query time on Windows
|
||||||
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||||
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#if _POSIX_C_SOURCE < 199309L
|
#if _POSIX_C_SOURCE < 199309L
|
||||||
#undef _POSIX_C_SOURCE
|
#undef _POSIX_C_SOURCE
|
||||||
|
|
|
||||||
75
src/models.c
75
src/models.c
|
|
@ -2084,6 +2084,61 @@ Mesh GenMeshCylinder(float radius, float height, int slices)
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate cone/pyramid mesh
|
||||||
|
Mesh GenMeshCone(float radius, float height, int slices)
|
||||||
|
{
|
||||||
|
Mesh mesh = { 0 };
|
||||||
|
|
||||||
|
if (slices >= 3)
|
||||||
|
{
|
||||||
|
// Instance a cone that sits on the Z=0 plane using the given tessellation
|
||||||
|
// levels across the UV domain. Think of "slices" like a number of pizza
|
||||||
|
// slices, and "stacks" like a number of stacked rings.
|
||||||
|
// Height and radius are both 1.0, but they can easily be changed with par_shapes_scale
|
||||||
|
par_shapes_mesh *cone = par_shapes_create_cone(slices, 8);
|
||||||
|
par_shapes_scale(cone, radius, radius, height);
|
||||||
|
par_shapes_rotate(cone, -PI/2.0f, (float[]){ 1, 0, 0 });
|
||||||
|
par_shapes_rotate(cone, PI/2.0f, (float[]){ 0, 1, 0 });
|
||||||
|
|
||||||
|
// Generate an orientable disk shape (bottom cap)
|
||||||
|
par_shapes_mesh *capBottom = par_shapes_create_disk(radius, slices, (float[]){ 0, 0, 0 }, (float[]){ 0, 0, -1 });
|
||||||
|
capBottom->tcoords = PAR_MALLOC(float, 2*capBottom->npoints);
|
||||||
|
for (int i = 0; i < 2*capBottom->npoints; i++) capBottom->tcoords[i] = 0.95f;
|
||||||
|
par_shapes_rotate(capBottom, PI/2.0f, (float[]){ 1, 0, 0 });
|
||||||
|
|
||||||
|
par_shapes_merge_and_free(cone, capBottom);
|
||||||
|
|
||||||
|
mesh.vertices = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));
|
||||||
|
mesh.texcoords = (float *)RL_MALLOC(cone->ntriangles*3*2*sizeof(float));
|
||||||
|
mesh.normals = (float *)RL_MALLOC(cone->ntriangles*3*3*sizeof(float));
|
||||||
|
|
||||||
|
mesh.vertexCount = cone->ntriangles*3;
|
||||||
|
mesh.triangleCount = cone->ntriangles;
|
||||||
|
|
||||||
|
for (int k = 0; k < mesh.vertexCount; k++)
|
||||||
|
{
|
||||||
|
mesh.vertices[k*3] = cone->points[cone->triangles[k]*3];
|
||||||
|
mesh.vertices[k*3 + 1] = cone->points[cone->triangles[k]*3 + 1];
|
||||||
|
mesh.vertices[k*3 + 2] = cone->points[cone->triangles[k]*3 + 2];
|
||||||
|
|
||||||
|
mesh.normals[k*3] = cone->normals[cone->triangles[k]*3];
|
||||||
|
mesh.normals[k*3 + 1] = cone->normals[cone->triangles[k]*3 + 1];
|
||||||
|
mesh.normals[k*3 + 2] = cone->normals[cone->triangles[k]*3 + 2];
|
||||||
|
|
||||||
|
mesh.texcoords[k*2] = cone->tcoords[cone->triangles[k]*2];
|
||||||
|
mesh.texcoords[k*2 + 1] = cone->tcoords[cone->triangles[k]*2 + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
par_shapes_free_mesh(cone);
|
||||||
|
|
||||||
|
// Upload vertex data to GPU (static mesh)
|
||||||
|
UploadMesh(&mesh, false);
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "MESH: Failed to generate mesh: cone");
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate torus mesh
|
// Generate torus mesh
|
||||||
Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
|
Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
|
||||||
{
|
{
|
||||||
|
|
@ -3123,11 +3178,10 @@ RayCollision GetRayCollisionBox(Ray ray, BoundingBox box)
|
||||||
collision.normal = Vector3Scale(collision.normal, 2.01f);
|
collision.normal = Vector3Scale(collision.normal, 2.01f);
|
||||||
collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));
|
collision.normal = Vector3Divide(collision.normal, Vector3Subtract(box.max, box.min));
|
||||||
// The relevant elemets of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
|
// The relevant elemets of the vector are now slightly larger than 1.0f (or smaller than -1.0f)
|
||||||
// and the others are somewhere between -1.0 and 1.0
|
// and the others are somewhere between -1.0 and 1.0 casting to int is exactly our wanted normal!
|
||||||
// casting to int is exactly our wanted normal!
|
collision.normal.x = (float)((int)collision.normal.x);
|
||||||
collision.normal.x = (int)collision.normal.x;
|
collision.normal.y = (float)((int)collision.normal.y);
|
||||||
collision.normal.y = (int)collision.normal.y;
|
collision.normal.z = (float)((int)collision.normal.z);
|
||||||
collision.normal.z = (int)collision.normal.z;
|
|
||||||
|
|
||||||
collision.normal = Vector3Normalize(collision.normal);
|
collision.normal = Vector3Normalize(collision.normal);
|
||||||
|
|
||||||
|
|
@ -3316,7 +3370,7 @@ static Model LoadOBJ(const char *fileName)
|
||||||
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName);
|
||||||
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes/%i materials", fileName, meshCount, materialCount);
|
||||||
|
|
||||||
model.meshCount = materialCount; // TODO: REVIEW!!!
|
model.meshCount = materialCount;
|
||||||
|
|
||||||
// Init model materials array
|
// Init model materials array
|
||||||
if (materialCount > 0)
|
if (materialCount > 0)
|
||||||
|
|
@ -3335,7 +3389,7 @@ static Model LoadOBJ(const char *fileName)
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
// Count the faces for each material
|
// Count the faces for each material
|
||||||
int *matFaces = RL_CALLOC(meshCount, sizeof(int));
|
int *matFaces = RL_CALLOC(materialCount, sizeof(int));
|
||||||
|
|
||||||
for (unsigned int mi = 0; mi < meshCount; mi++)
|
for (unsigned int mi = 0; mi < meshCount; mi++)
|
||||||
{
|
{
|
||||||
|
|
@ -3346,7 +3400,6 @@ static Model LoadOBJ(const char *fileName)
|
||||||
matFaces[idx]++;
|
matFaces[idx]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------
|
//--------------------------------------
|
||||||
// Create the material meshes
|
// Create the material meshes
|
||||||
|
|
||||||
|
|
@ -4937,7 +4990,7 @@ static ModelAnimation *LoadGLTFModelAnimations(const char *fileName, int *animCo
|
||||||
{
|
{
|
||||||
output->framePoses[frame] = RL_MALLOC(output->boneCount*sizeof(Transform));
|
output->framePoses[frame] = RL_MALLOC(output->boneCount*sizeof(Transform));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < output->boneCount; i++)
|
for (int i = 0; i < output->boneCount; i++)
|
||||||
{
|
{
|
||||||
if (data->nodes[i].has_translation) memcpy(&output->framePoses[frame][i].translation, data->nodes[i].translation, 3*sizeof(float));
|
if (data->nodes[i].has_translation) memcpy(&output->framePoses[frame][i].translation, data->nodes[i].translation, 3*sizeof(float));
|
||||||
else output->framePoses[frame][i].translation = Vector3Zero();
|
else output->framePoses[frame][i].translation = Vector3Zero();
|
||||||
|
|
@ -5130,7 +5183,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu
|
||||||
outModel->meshes[(*primitiveIndex)].vertices = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false);
|
outModel->meshes[(*primitiveIndex)].vertices = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false);
|
||||||
|
|
||||||
// Transform using the nodes matrix attributes
|
// Transform using the nodes matrix attributes
|
||||||
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
|
for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
|
||||||
{
|
{
|
||||||
Vector3 vertex = {
|
Vector3 vertex = {
|
||||||
outModel->meshes[(*primitiveIndex)].vertices[(v*3 + 0)],
|
outModel->meshes[(*primitiveIndex)].vertices[(v*3 + 0)],
|
||||||
|
|
@ -5156,7 +5209,7 @@ void LoadGLTFMesh(cgltf_data* data, cgltf_mesh* mesh, Model* outModel, Matrix cu
|
||||||
outModel->meshes[(*primitiveIndex)].normals = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false);
|
outModel->meshes[(*primitiveIndex)].normals = ReadGLTFValuesAs(acc, cgltf_component_type_r_32f, false);
|
||||||
|
|
||||||
// Transform using the nodes matrix attributes
|
// Transform using the nodes matrix attributes
|
||||||
for (unsigned int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
|
for (int v = 0; v < outModel->meshes[(*primitiveIndex)].vertexCount; v++)
|
||||||
{
|
{
|
||||||
Vector3 normal = {
|
Vector3 normal = {
|
||||||
outModel->meshes[(*primitiveIndex)].normals[(v*3 + 0)],
|
outModel->meshes[(*primitiveIndex)].normals[(v*3 + 0)],
|
||||||
|
|
|
||||||
79
src/raylib.h
79
src/raylib.h
|
|
@ -81,19 +81,18 @@
|
||||||
|
|
||||||
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
|
||||||
|
|
||||||
#define RAYLIB_VERSION "3.8-dev"
|
#define RAYLIB_VERSION "4.0-dev"
|
||||||
|
|
||||||
|
#ifndef RLAPI
|
||||||
|
#define RLAPI // We are building or using rlgl as a static library (or Linux shared library)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Microsoft attibutes to tell compiler that symbols are imported/exported from a .dll
|
|
||||||
#if defined(BUILD_LIBTYPE_SHARED)
|
#if defined(BUILD_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 shared library (.dll)
|
||||||
#elif defined(USE_LIBTYPE_SHARED)
|
#elif defined(USE_LIBTYPE_SHARED)
|
||||||
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll)
|
||||||
#else
|
|
||||||
#define RLAPI // We are building or using raylib as a static library
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
#define RLAPI // We are building or using raylib as a static library (or Linux shared library)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -282,23 +281,23 @@ typedef struct NPatchInfo {
|
||||||
int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1
|
int layout; // Layout of the n-patch: 3x3, 1x3 or 3x1
|
||||||
} NPatchInfo;
|
} NPatchInfo;
|
||||||
|
|
||||||
// CharInfo, font character info
|
// GlyphInfo, font characters glyphs info
|
||||||
typedef struct CharInfo {
|
typedef struct GlyphInfo {
|
||||||
int value; // Character value (Unicode)
|
int value; // Character value (Unicode)
|
||||||
int offsetX; // Character offset X when drawing
|
int offsetX; // Character offset X when drawing
|
||||||
int offsetY; // Character offset Y when drawing
|
int offsetY; // Character offset Y when drawing
|
||||||
int advanceX; // Character advance position X
|
int advanceX; // Character advance position X
|
||||||
Image image; // Character image data
|
Image image; // Character image data
|
||||||
} CharInfo;
|
} GlyphInfo;
|
||||||
|
|
||||||
// Font, font texture and CharInfo 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 charsCount; // Number of characters
|
||||||
int charsPadding; // Padding around the chars
|
int charsPadding; // Padding around the chars
|
||||||
Texture2D texture; // Characters texture atlas
|
Texture2D texture; // Characters texture atlas
|
||||||
Rectangle *recs; // Characters rectangles in texture
|
Rectangle *recs; // Characters rectangles in texture
|
||||||
CharInfo *chars; // Characters info data
|
GlyphInfo *chars; // Characters glyphs info data
|
||||||
} Font;
|
} Font;
|
||||||
|
|
||||||
// Camera, defines position/orientation in 3d space
|
// Camera, defines position/orientation in 3d space
|
||||||
|
|
@ -894,11 +893,6 @@ typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, unsigned
|
||||||
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
|
||||||
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
typedef bool (*SaveFileTextCallback)(const char *fileName, char *text); // FileIO: Save text data
|
||||||
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
@ -908,6 +902,10 @@ extern "C" { // Prevents name mangling of functions
|
||||||
// Window and Graphics Device Functions (Module: core)
|
// Window and Graphics Device Functions (Module: core)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize window and OpenGL context
|
||||||
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
RLAPI bool WindowShouldClose(void); // Check if KEY_ESCAPE pressed or Close icon pressed
|
||||||
|
|
@ -1077,8 +1075,8 @@ RLAPI bool IsKeyDown(int key); // Check if a key
|
||||||
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once
|
||||||
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed
|
||||||
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued
|
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
|
||||||
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued
|
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
|
||||||
|
|
||||||
// Input-related functions: gamepads
|
// Input-related functions: gamepads
|
||||||
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available
|
||||||
|
|
@ -1217,7 +1215,7 @@ RLAPI Image GenImageGradientRadial(int width, int height, float density, Color i
|
||||||
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked
|
||||||
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise
|
||||||
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise
|
||||||
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells
|
RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells
|
||||||
|
|
||||||
// Image manipulation functions
|
// Image manipulation functions
|
||||||
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
|
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
|
||||||
|
|
@ -1320,34 +1318,42 @@ RLAPI Font LoadFont(const char *fileName);
|
||||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters
|
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int *fontChars, int charsCount); // Load font from file with extended parameters
|
||||||
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
|
RLAPI Font 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 charsCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
|
||||||
RLAPI CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
|
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
|
||||||
RLAPI Image GenImageFontAtlas(const CharInfo *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 charsCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
|
||||||
RLAPI void UnloadFontData(CharInfo *chars, int charsCount); // Unload font chars info data (RAM)
|
RLAPI void UnloadFontData(GlyphInfo *chars, int charsCount); // 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
|
||||||
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
RLAPI void DrawFPS(int posX, int posY); // Draw current FPS
|
||||||
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||||
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
|
||||||
//RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint);
|
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
|
||||||
RLAPI void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint); // Draw text using font inside rectangle limits
|
|
||||||
RLAPI void DrawTextRecEx(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint); // Draw text using font inside rectangle limits with support for text selection
|
|
||||||
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
|
||||||
|
|
||||||
// Text misc. functions
|
// Text font info functions
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get index position for a unicode character on font
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
RLAPI GlyphInfo GetGlyphInfo(Font font, int codepoint); // Get glyph font info data for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
RLAPI Rectangle GetGlyphAtlasRec(Font font, int codepoint); // Get glyph rectangle in font atlas for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
|
||||||
// Text strings management functions (no utf8 strings, only byte chars)
|
// Text codepoints management functions (unicode characters)
|
||||||
|
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||||
|
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
||||||
|
RLAPI int GetCodepointsCount(const char *text); // Get total number of codepoints in a UTF-8 encoded string
|
||||||
|
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF-8 encoded string, 0x3f('?') is returned on failure
|
||||||
|
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength); // Encode one codepoint into UTF-8 byte array (array length returned as parameter)
|
||||||
|
RLAPI char *TextCodepointsToUTF8(int *codepoints, int length); // Encode text as codepoints array into UTF-8 text string (WARNING: memory must be freed!)
|
||||||
|
|
||||||
|
// Text strings management functions (no UTF-8 strings, only byte chars)
|
||||||
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
// NOTE: Some strings allocate memory internally for returned strings, just be careful!
|
||||||
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
|
||||||
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal
|
||||||
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
|
||||||
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf style)
|
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
|
||||||
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
|
||||||
RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (memory must be freed!)
|
RLAPI char *TextReplace(char *text, const char *replace, const char *by); // Replace text string (WARNING: memory must be freed!)
|
||||||
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (memory must be freed!)
|
RLAPI char *TextInsert(const char *text, const char *insert, int position); // Insert text in a position (WARNING: memory must be freed!)
|
||||||
RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
RLAPI const char *TextJoin(const char **textList, int count, const char *delimiter); // Join text strings with delimiter
|
||||||
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
RLAPI const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings
|
||||||
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
|
RLAPI void TextAppend(char *text, const char *append, int *position); // Append text at specific position and move cursor!
|
||||||
|
|
@ -1356,14 +1362,6 @@ RLAPI const char *TextToUpper(const char *text); // Get upp
|
||||||
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
RLAPI const char *TextToLower(const char *text); // Get lower case version of provided string
|
||||||
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
RLAPI const char *TextToPascal(const char *text); // Get Pascal case notation version of provided string
|
||||||
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
|
RLAPI int TextToInteger(const char *text); // Get integer value from text (negative values not supported)
|
||||||
RLAPI char *TextToUtf8(int *codepoints, int length); // Encode text codepoint into utf8 text (memory must be freed!)
|
|
||||||
|
|
||||||
// UTF8 text strings management functions
|
|
||||||
RLAPI int *LoadCodepoints(const char *text, int *count); // Load all codepoints from a UTF8 text string, codepoints count returned by parameter
|
|
||||||
RLAPI void UnloadCodepoints(int *codepoints); // Unload codepoints data from memory
|
|
||||||
RLAPI int GetCodepointsCount(const char *text); // Get total number of characters (codepoints) in a UTF8 encoded string
|
|
||||||
RLAPI int GetCodepoint(const char *text, int *bytesProcessed); // Get next codepoint in a UTF8 encoded string, 0x3f('?') is returned on failure
|
|
||||||
RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength); // Encode codepoint into utf8 text (char array length returned as parameter)
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Basic 3d Shapes Drawing Functions (Module: models)
|
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||||
|
|
@ -1428,6 +1426,7 @@ RLAPI Mesh GenMeshCube(float width, float height, float length);
|
||||||
RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere)
|
RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere)
|
||||||
RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap)
|
RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices); // Generate half-sphere mesh (no bottom cap)
|
||||||
RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh
|
RLAPI Mesh GenMeshCylinder(float radius, float height, int slices); // Generate cylinder mesh
|
||||||
|
RLAPI Mesh GenMeshCone(float radius, float height, int slices); // Generate cone/pyramid mesh
|
||||||
RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh
|
RLAPI Mesh GenMeshTorus(float radius, float size, int radSeg, int sides); // Generate torus mesh
|
||||||
RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh
|
RLAPI Mesh GenMeshKnot(float radius, float size, int radSeg, int sides); // Generate trefoil knot mesh
|
||||||
RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data
|
RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data
|
||||||
|
|
|
||||||
|
|
@ -138,11 +138,11 @@ typedef struct Matrix {
|
||||||
|
|
||||||
// NOTE: Helper types to be used instead of array return types for *ToFloat functions
|
// NOTE: Helper types to be used instead of array return types for *ToFloat functions
|
||||||
typedef struct float3 {
|
typedef struct float3 {
|
||||||
float v[3];
|
float v[3];
|
||||||
} float3;
|
} float3;
|
||||||
|
|
||||||
typedef struct float16 {
|
typedef struct float16 {
|
||||||
float v[16];
|
float v[16];
|
||||||
} float16;
|
} float16;
|
||||||
|
|
||||||
#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs()
|
#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), fminf(), fmaxf(), fabs()
|
||||||
|
|
|
||||||
101
src/rlgl.h
101
src/rlgl.h
|
|
@ -457,13 +457,14 @@ typedef enum {
|
||||||
RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
|
RL_SHADER_ATTRIB_VEC4 // Shader attribute type: vec4 (4 float)
|
||||||
} rlShaderAttributeDataType;
|
} rlShaderAttributeDataType;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Matrix operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
// Functions Declaration - Matrix operations
|
|
||||||
//------------------------------------------------------------------------------------
|
|
||||||
RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
RLAPI void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
||||||
RLAPI void rlPushMatrix(void); // Push the current matrix to stack
|
RLAPI void rlPushMatrix(void); // Push the current matrix to stack
|
||||||
RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack
|
RLAPI void rlPopMatrix(void); // Pop lattest inserted matrix from stack
|
||||||
|
|
@ -506,8 +507,8 @@ RLAPI void rlDisableVertexBufferElement(void); // Disable vertex buffer
|
||||||
RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
|
RLAPI void rlEnableVertexAttribute(unsigned int index); // Enable vertex attribute index
|
||||||
RLAPI void rlDisableVertexAttribute(unsigned int index);// Disable vertex attribute index
|
RLAPI void rlDisableVertexAttribute(unsigned int index);// Disable vertex attribute index
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer);
|
RLAPI void rlEnableStatePointer(int vertexAttribType, void *buffer); // Enable attribute state pointer
|
||||||
RLAPI void rlDisableStatePointer(int vertexAttribType);
|
RLAPI void rlDisableStatePointer(int vertexAttribType); // Disable attribute state pointer
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Textures state
|
// Textures state
|
||||||
|
|
@ -525,8 +526,11 @@ RLAPI void rlDisableShader(void); // Disable shader progra
|
||||||
// Framebuffer state
|
// Framebuffer state
|
||||||
RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
|
RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
|
||||||
RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
|
RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
|
||||||
|
RLAPI void rlActiveDrawBuffers(int count); // Activate multiple draw color buffers
|
||||||
|
|
||||||
// General render state
|
// General render state
|
||||||
|
RLAPI void rlEnableColorBlend(void); // Enable color blending
|
||||||
|
RLAPI void rlDisableColorBlend(void); // Disable color blending
|
||||||
RLAPI void rlEnableDepthTest(void); // Enable depth test
|
RLAPI void rlEnableDepthTest(void); // Enable depth test
|
||||||
RLAPI void rlDisableDepthTest(void); // Disable depth test
|
RLAPI void rlDisableDepthTest(void); // Disable depth test
|
||||||
RLAPI void rlEnableDepthMask(void); // Enable depth write
|
RLAPI void rlEnableDepthMask(void); // Enable depth write
|
||||||
|
|
@ -584,7 +588,7 @@ RLAPI void rlSetTexture(unsigned int id); // Set current texture for r
|
||||||
RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported
|
RLAPI unsigned int rlLoadVertexArray(void); // Load vertex array (vao) if supported
|
||||||
RLAPI unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
|
RLAPI unsigned int rlLoadVertexBuffer(void *buffer, int size, bool dynamic); // Load a vertex buffer attribute
|
||||||
RLAPI unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic); // Load a new attributes element buffer
|
RLAPI unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic); // Load a new attributes element buffer
|
||||||
RLAPI void rlUpdateVertexBuffer(int bufferId, void *data, int dataSize, int offset); // Update GPU buffer with new data
|
RLAPI void rlUpdateVertexBuffer(unsigned int bufferId, void *data, int dataSize, int offset); // Update GPU buffer with new data
|
||||||
RLAPI void rlUnloadVertexArray(unsigned int vaoId);
|
RLAPI void rlUnloadVertexArray(unsigned int vaoId);
|
||||||
RLAPI void rlUnloadVertexBuffer(unsigned int vboId);
|
RLAPI void rlUnloadVertexBuffer(unsigned int vboId);
|
||||||
RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer);
|
RLAPI void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer);
|
||||||
|
|
@ -639,6 +643,7 @@ RLAPI void rlSetMatrixViewOffsetStereo(Matrix right, Matrix left); // Set e
|
||||||
// Quick and dirty cube/quad buffers load->draw->unload
|
// Quick and dirty cube/quad buffers load->draw->unload
|
||||||
RLAPI void rlLoadDrawCube(void); // Load and draw a cube
|
RLAPI void rlLoadDrawCube(void); // Load and draw a cube
|
||||||
RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1544,6 +1549,49 @@ void rlDisableFramebuffer(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Activate multiple draw color buffers
|
||||||
|
// NOTE: One color buffer is always active by default
|
||||||
|
void rlActiveDrawBuffers(int count)
|
||||||
|
{
|
||||||
|
#if (defined(GRAPHICS_API_OPENGL_33) && defined(SUPPORT_RENDER_TEXTURES_HINT))
|
||||||
|
// NOTE: Maximum number of draw buffers supported is implementation dependant,
|
||||||
|
// it can be queried with glGet*() but it must be at least 8
|
||||||
|
//GLint maxDrawBuffers = 0;
|
||||||
|
//glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
if (count > 8) TRACELOG(LOG_WARNING, "GL: Max color buffers limited to 8");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int buffers[8] = {
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_COLOR_ATTACHMENT1,
|
||||||
|
GL_COLOR_ATTACHMENT2,
|
||||||
|
GL_COLOR_ATTACHMENT3,
|
||||||
|
GL_COLOR_ATTACHMENT4,
|
||||||
|
GL_COLOR_ATTACHMENT5,
|
||||||
|
GL_COLOR_ATTACHMENT6,
|
||||||
|
GL_COLOR_ATTACHMENT7,
|
||||||
|
};
|
||||||
|
|
||||||
|
glDrawBuffers(count, buffers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "GL: One color buffer active by default");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// General render state configuration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Enable color blending
|
||||||
|
void rlEnableColorBlend(void) { glEnable(GL_BLEND); }
|
||||||
|
|
||||||
|
// Disable color blending
|
||||||
|
void rlDisableColorBlend(void) { glDisable(GL_BLEND); }
|
||||||
|
|
||||||
// Enable depth test
|
// Enable depth test
|
||||||
void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
|
void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
|
||||||
|
|
||||||
|
|
@ -1588,11 +1636,9 @@ void rlDisableWireMode(void)
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the line drawing width
|
// Set the line drawing width
|
||||||
void rlSetLineWidth(float width)
|
void rlSetLineWidth(float width) { glLineWidth(width); }
|
||||||
{
|
|
||||||
glLineWidth(width);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the line drawing width
|
// Get the line drawing width
|
||||||
float rlGetLineWidth(void)
|
float rlGetLineWidth(void)
|
||||||
|
|
@ -3179,6 +3225,7 @@ unsigned int rlLoadVertexBufferElement(void *buffer, int size, bool dynamic)
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable vertex buffer (VBO)
|
||||||
void rlEnableVertexBuffer(unsigned int id)
|
void rlEnableVertexBuffer(unsigned int id)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3186,6 +3233,7 @@ void rlEnableVertexBuffer(unsigned int id)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable vertex buffer (VBO)
|
||||||
void rlDisableVertexBuffer(void)
|
void rlDisableVertexBuffer(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3193,6 +3241,7 @@ void rlDisableVertexBuffer(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable vertex buffer element (VBO element)
|
||||||
void rlEnableVertexBufferElement(unsigned int id)
|
void rlEnableVertexBufferElement(unsigned int id)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3200,6 +3249,7 @@ void rlEnableVertexBufferElement(unsigned int id)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable vertex buffer element (VBO element)
|
||||||
void rlDisableVertexBufferElement(void)
|
void rlDisableVertexBufferElement(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3207,16 +3257,27 @@ void rlDisableVertexBufferElement(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update GPU buffer with new data
|
// Update vertex buffer with new data
|
||||||
// NOTE: dataSize and offset must be provided in bytes
|
// NOTE: dataSize and offset must be provided in bytes
|
||||||
void rlUpdateVertexBuffer(int bufferId, void *data, int dataSize, int offset)
|
void rlUpdateVertexBuffer(unsigned int id, void *data, int dataSize, int offset)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
|
glBindBuffer(GL_ARRAY_BUFFER, id);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data);
|
glBufferSubData(GL_ARRAY_BUFFER, offset, dataSize, data);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update vertex buffer elements with new data
|
||||||
|
// NOTE: dataSize and offset must be provided in bytes
|
||||||
|
void rlUpdateVertexBufferElements(unsigned int id, void *data, int dataSize, int offset)
|
||||||
|
{
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
|
||||||
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, dataSize, data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable vertex array object (VAO)
|
||||||
bool rlEnableVertexArray(unsigned int vaoId)
|
bool rlEnableVertexArray(unsigned int vaoId)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
@ -3230,6 +3291,7 @@ bool rlEnableVertexArray(unsigned int vaoId)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable vertex array object (VAO)
|
||||||
void rlDisableVertexArray(void)
|
void rlDisableVertexArray(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3237,6 +3299,7 @@ void rlDisableVertexArray(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable vertex attribute index
|
||||||
void rlEnableVertexAttribute(unsigned int index)
|
void rlEnableVertexAttribute(unsigned int index)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3244,6 +3307,7 @@ void rlEnableVertexAttribute(unsigned int index)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable vertex attribute index
|
||||||
void rlDisableVertexAttribute(unsigned int index)
|
void rlDisableVertexAttribute(unsigned int index)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3251,16 +3315,19 @@ void rlDisableVertexAttribute(unsigned int index)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw vertex array
|
||||||
void rlDrawVertexArray(int offset, int count)
|
void rlDrawVertexArray(int offset, int count)
|
||||||
{
|
{
|
||||||
glDrawArrays(GL_TRIANGLES, offset, count);
|
glDrawArrays(GL_TRIANGLES, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw vertex array elements
|
||||||
void rlDrawVertexArrayElements(int offset, int count, void *buffer)
|
void rlDrawVertexArrayElements(int offset, int count, void *buffer)
|
||||||
{
|
{
|
||||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset);
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (unsigned short *)buffer + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw vertex array instanced
|
||||||
void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3268,6 +3335,7 @@ void rlDrawVertexArrayInstanced(int offset, int count, int instances)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw vertex array elements instanced
|
||||||
void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int instances)
|
void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int instances)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3276,6 +3344,7 @@ void rlDrawVertexArrayElementsInstanced(int offset, int count, void *buffer, int
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
// Enable vertex state pointer
|
||||||
void rlEnableStatePointer(int vertexAttribType, void *buffer)
|
void rlEnableStatePointer(int vertexAttribType, void *buffer)
|
||||||
{
|
{
|
||||||
if (buffer != NULL) glEnableClientState(vertexAttribType);
|
if (buffer != NULL) glEnableClientState(vertexAttribType);
|
||||||
|
|
@ -3290,12 +3359,14 @@ void rlEnableStatePointer(int vertexAttribType, void *buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable vertex state pointer
|
||||||
void rlDisableStatePointer(int vertexAttribType)
|
void rlDisableStatePointer(int vertexAttribType)
|
||||||
{
|
{
|
||||||
glDisableClientState(vertexAttribType);
|
glDisableClientState(vertexAttribType);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Load vertex array object (VAO)
|
||||||
unsigned int rlLoadVertexArray(void)
|
unsigned int rlLoadVertexArray(void)
|
||||||
{
|
{
|
||||||
unsigned int vaoId = 0;
|
unsigned int vaoId = 0;
|
||||||
|
|
@ -3308,6 +3379,7 @@ unsigned int rlLoadVertexArray(void)
|
||||||
return vaoId;
|
return vaoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set vertex attribute
|
||||||
void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer)
|
void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool normalized, int stride, void *pointer)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3315,6 +3387,7 @@ void rlSetVertexAttribute(unsigned int index, int compSize, int type, bool norma
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set vertex attribute divisor
|
||||||
void rlSetVertexAttributeDivisor(unsigned int index, int divisor)
|
void rlSetVertexAttributeDivisor(unsigned int index, int divisor)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3322,6 +3395,7 @@ void rlSetVertexAttributeDivisor(unsigned int index, int divisor)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unload vertex array object (VAO)
|
||||||
void rlUnloadVertexArray(unsigned int vaoId)
|
void rlUnloadVertexArray(unsigned int vaoId)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
@ -3334,6 +3408,7 @@ void rlUnloadVertexArray(unsigned int vaoId)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unload vertex buffer (VBO)
|
||||||
void rlUnloadVertexBuffer(unsigned int vboId)
|
void rlUnloadVertexBuffer(unsigned int vboId)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
|
||||||
211
src/text.c
211
src/text.c
|
|
@ -53,14 +53,15 @@
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "utils.h" // Required for: LoadFileText()
|
||||||
|
#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 -> Only DrawTextPro()
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free()
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
#include <stdio.h> // Required for: vsprintf()
|
#include <stdio.h> // Required for: vsprintf()
|
||||||
#include <string.h> // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
|
#include <string.h> // Required for: strcmp(), strstr(), strcpy(), strncpy() [Used in TextReplace()], sscanf() [Used in LoadBMFont()]
|
||||||
#include <stdarg.h> // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
|
#include <stdarg.h> // Required for: va_list, va_start(), vsprintf(), va_end() [Used in TextFormat()]
|
||||||
#include <ctype.h> // Requried for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
#include <ctype.h> // Requried for: toupper(), tolower() [Used in TextToUpper(), TextToLower()]
|
||||||
|
|
||||||
#include "utils.h" // Required for: LoadFileText()
|
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
#define STB_RECT_PACK_IMPLEMENTATION
|
#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
#include "external/stb_rect_pack.h" // Required for: ttf font rectangles packaging
|
||||||
|
|
@ -125,7 +126,7 @@ extern void LoadFontDefault(void)
|
||||||
{
|
{
|
||||||
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
#define BIT_CHECK(a,b) ((a) & (1u << (b)))
|
||||||
|
|
||||||
// NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
// NOTE: Using UTF-8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||||
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
// Ref: http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||||
|
|
||||||
defaultFont.charsCount = 224; // Number of chars included in our default font
|
defaultFont.charsCount = 224; // Number of chars included in our default font
|
||||||
|
|
@ -224,7 +225,7 @@ extern void LoadFontDefault(void)
|
||||||
|
|
||||||
// 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 = (CharInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(CharInfo));
|
defaultFont.chars = (GlyphInfo *)RL_MALLOC(defaultFont.charsCount*sizeof(GlyphInfo));
|
||||||
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle));
|
defaultFont.recs = (Rectangle *)RL_MALLOC(defaultFont.charsCount*sizeof(Rectangle));
|
||||||
|
|
||||||
int currentLine = 0;
|
int currentLine = 0;
|
||||||
|
|
@ -453,7 +454,7 @@ Font LoadFontFromImage(Image image, Color key, int firstChar)
|
||||||
|
|
||||||
// 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 = (CharInfo *)RL_MALLOC(font.charsCount*sizeof(CharInfo));
|
font.chars = (GlyphInfo *)RL_MALLOC(font.charsCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle));
|
font.recs = (Rectangle *)RL_MALLOC(font.charsCount*sizeof(Rectangle));
|
||||||
|
|
||||||
for (int i = 0; i < font.charsCount; i++)
|
for (int i = 0; i < font.charsCount; i++)
|
||||||
|
|
@ -523,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
|
||||||
CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type)
|
GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, int *fontChars, int charsCount, int type)
|
||||||
{
|
{
|
||||||
// NOTE: Using some SDF generation default values,
|
// 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
|
||||||
|
|
@ -540,7 +541,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize
|
||||||
#define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold
|
#define FONT_BITMAP_ALPHA_THRESHOLD 80 // Bitmap (B&W) font generation alpha threshold
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CharInfo *chars = NULL;
|
GlyphInfo *chars = NULL;
|
||||||
|
|
||||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||||
// Load font data (including pixel data) from TTF memory file
|
// Load font data (including pixel data) from TTF memory file
|
||||||
|
|
@ -573,7 +574,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize
|
||||||
genFontChars = true;
|
genFontChars = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo));
|
chars = (GlyphInfo *)RL_MALLOC(charsCount*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 < charsCount; i++)
|
||||||
|
|
@ -649,7 +650,7 @@ CharInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize
|
||||||
// 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 CharInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod)
|
Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int charsCount, int fontSize, int padding, int packMethod)
|
||||||
{
|
{
|
||||||
Image atlas = { 0 };
|
Image atlas = { 0 };
|
||||||
|
|
||||||
|
|
@ -792,7 +793,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Unload font chars info data (RAM)
|
// Unload font chars info data (RAM)
|
||||||
void UnloadFontData(CharInfo *chars, int charsCount)
|
void UnloadFontData(GlyphInfo *chars, int charsCount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image);
|
for (int i = 0; i < charsCount; i++) UnloadImage(chars[i].image);
|
||||||
|
|
||||||
|
|
@ -890,140 +891,18 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text using font inside rectangle limits
|
// Draw text using Font and pro parameters (rotation)
|
||||||
void DrawTextRec(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint)
|
void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint)
|
||||||
{
|
{
|
||||||
DrawTextRecEx(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE);
|
rlPushMatrix();
|
||||||
}
|
|
||||||
|
|
||||||
// Draw text using font inside rectangle limits with support for text selection
|
rlTranslatef(position.x, position.y, 0.0f);
|
||||||
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)
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
||||||
{
|
rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||||
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
|
||||||
|
DrawTextEx(font, text, (Vector2){ 0.0f, 0.0f }, fontSize, spacing, tint);
|
||||||
float textOffsetY = 0; // Offset between lines (on line break '\n')
|
|
||||||
float textOffsetX = 0.0f; // Offset X to next character to draw
|
rlPopMatrix();
|
||||||
|
|
||||||
float scaleFactor = fontSize/(float)font.baseSize; // Character quad scaling factor
|
|
||||||
|
|
||||||
// Word/character wrapping mechanism variables
|
|
||||||
enum { MEASURE_STATE = 0, DRAW_STATE = 1 };
|
|
||||||
int state = wordWrap? MEASURE_STATE : DRAW_STATE;
|
|
||||||
|
|
||||||
int startLine = -1; // Index where to begin drawing (where a line begins)
|
|
||||||
int endLine = -1; // Index where to stop drawing (where a line ends)
|
|
||||||
int lastk = -1; // Holds last value of the character position
|
|
||||||
|
|
||||||
for (int i = 0, k = 0; i < length; i++, k++)
|
|
||||||
{
|
|
||||||
// Get next codepoint from byte string and glyph index in font
|
|
||||||
int codepointByteCount = 0;
|
|
||||||
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
|
|
||||||
int index = GetGlyphIndex(font, codepoint);
|
|
||||||
|
|
||||||
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
|
||||||
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
|
||||||
if (codepoint == 0x3f) codepointByteCount = 1;
|
|
||||||
i += (codepointByteCount - 1);
|
|
||||||
|
|
||||||
float glyphWidth = 0;
|
|
||||||
if (codepoint != '\n')
|
|
||||||
{
|
|
||||||
glyphWidth = (font.chars[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.chars[index].advanceX*scaleFactor;
|
|
||||||
|
|
||||||
if (i + 1 < length) glyphWidth = glyphWidth + spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: When wordWrap is ON we first measure how much of the text we can draw before going outside of the rec container
|
|
||||||
// We store this info in startLine and endLine, then we change states, draw the text between those two variables
|
|
||||||
// and change states again and again recursively until the end of the text (or until we get outside of the container).
|
|
||||||
// When wordWrap is OFF we don't need the measure state so we go to the drawing state immediately
|
|
||||||
// and begin drawing on the next line before we can get outside the container.
|
|
||||||
if (state == MEASURE_STATE)
|
|
||||||
{
|
|
||||||
// TODO: There are multiple types of spaces in UNICODE, maybe it's a good idea to add support for more
|
|
||||||
// Ref: http://jkorpela.fi/chars/spaces.html
|
|
||||||
if ((codepoint == ' ') || (codepoint == '\t') || (codepoint == '\n')) endLine = i;
|
|
||||||
|
|
||||||
if ((textOffsetX + glyphWidth) > rec.width)
|
|
||||||
{
|
|
||||||
endLine = (endLine < 1)? i : endLine;
|
|
||||||
if (i == endLine) endLine -= codepointByteCount;
|
|
||||||
if ((startLine + codepointByteCount) == endLine) endLine = (i - codepointByteCount);
|
|
||||||
|
|
||||||
state = !state;
|
|
||||||
}
|
|
||||||
else if ((i + 1) == length)
|
|
||||||
{
|
|
||||||
endLine = i;
|
|
||||||
state = !state;
|
|
||||||
}
|
|
||||||
else if (codepoint == '\n') state = !state;
|
|
||||||
|
|
||||||
if (state == DRAW_STATE)
|
|
||||||
{
|
|
||||||
textOffsetX = 0;
|
|
||||||
i = startLine;
|
|
||||||
glyphWidth = 0;
|
|
||||||
|
|
||||||
// Save character position when we switch states
|
|
||||||
int tmp = lastk;
|
|
||||||
lastk = k - 1;
|
|
||||||
k = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (codepoint == '\n')
|
|
||||||
{
|
|
||||||
if (!wordWrap)
|
|
||||||
{
|
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
|
||||||
textOffsetX = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!wordWrap && ((textOffsetX + glyphWidth) > rec.width))
|
|
||||||
{
|
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
|
||||||
textOffsetX = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When text overflows rectangle height limit, just stop drawing
|
|
||||||
if ((textOffsetY + font.baseSize*scaleFactor) > rec.height) break;
|
|
||||||
|
|
||||||
// Draw selection background
|
|
||||||
bool isGlyphSelected = false;
|
|
||||||
if ((selectStart >= 0) && (k >= selectStart) && (k < (selectStart + selectLength)))
|
|
||||||
{
|
|
||||||
DrawRectangleRec((Rectangle){ rec.x + textOffsetX - 1, rec.y + textOffsetY, glyphWidth, (float)font.baseSize*scaleFactor }, selectBackTint);
|
|
||||||
isGlyphSelected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw current character glyph
|
|
||||||
if ((codepoint != ' ') && (codepoint != '\t'))
|
|
||||||
{
|
|
||||||
DrawTextCodepoint(font, codepoint, (Vector2){ rec.x + textOffsetX, rec.y + textOffsetY }, fontSize, isGlyphSelected? selectTint : tint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wordWrap && (i == endLine))
|
|
||||||
{
|
|
||||||
textOffsetY += (font.baseSize + font.baseSize/2)*scaleFactor;
|
|
||||||
textOffsetX = 0;
|
|
||||||
startLine = endLine;
|
|
||||||
endLine = -1;
|
|
||||||
glyphWidth = 0;
|
|
||||||
selectStart += lastk - k;
|
|
||||||
k = lastk;
|
|
||||||
|
|
||||||
state = !state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textOffsetX += glyphWidth;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw one character (codepoint)
|
// Draw one character (codepoint)
|
||||||
|
|
@ -1123,6 +1002,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get index position for a unicode character on font
|
// Get index position for a unicode character on font
|
||||||
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
int GetGlyphIndex(Font font, int codepoint)
|
int GetGlyphIndex(Font font, int codepoint)
|
||||||
{
|
{
|
||||||
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
|
#ifndef GLYPH_NOTFOUND_CHAR_FALLBACK
|
||||||
|
|
@ -1149,6 +1029,28 @@ int GetGlyphIndex(Font font, int codepoint)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get glyph font info data for a codepoint (unicode character)
|
||||||
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
|
GlyphInfo GetGlyphInfo(Font font, int codepoint)
|
||||||
|
{
|
||||||
|
GlyphInfo info = { 0 };
|
||||||
|
|
||||||
|
info = font.chars[GetGlyphIndex(font, codepoint)];
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get glyph rectangle in font atlas for a codepoint (unicode character)
|
||||||
|
// NOTE: If codepoint is not found in the font it fallbacks to '?'
|
||||||
|
Rectangle GetGlyphAtlasRec(Font font, int codepoint)
|
||||||
|
{
|
||||||
|
Rectangle rec = { 0 };
|
||||||
|
|
||||||
|
rec = font.recs[GetGlyphIndex(font, codepoint)];
|
||||||
|
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Text strings management functions
|
// Text strings management functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -1446,7 +1348,7 @@ const char *TextToUpper(const char *text)
|
||||||
buffer[i] = (char)toupper(text[i]);
|
buffer[i] = (char)toupper(text[i]);
|
||||||
//if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
//if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
||||||
|
|
||||||
// TODO: Support Utf8 diacritics!
|
// TODO: Support UTF-8 diacritics!
|
||||||
//if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32;
|
//if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32;
|
||||||
}
|
}
|
||||||
else { buffer[i] = '\0'; break; }
|
else { buffer[i] = '\0'; break; }
|
||||||
|
|
@ -1499,10 +1401,10 @@ const char *TextToPascal(const char *text)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode text codepoint into utf8 text
|
// Encode text codepoint into UTF-8 text
|
||||||
// REQUIRES: memcpy()
|
// REQUIRES: memcpy()
|
||||||
// WARNING: Allocated memory should be manually freed
|
// WARNING: Allocated memory should be manually freed
|
||||||
char *TextToUtf8(int *codepoints, int length)
|
char *TextCodepointsToUTF8(int *codepoints, int length)
|
||||||
{
|
{
|
||||||
// We allocate enough memory fo fit all possible codepoints
|
// We allocate enough memory fo fit all possible codepoints
|
||||||
// NOTE: 5 bytes for every codepoint should be enough
|
// NOTE: 5 bytes for every codepoint should be enough
|
||||||
|
|
@ -1512,7 +1414,7 @@ char *TextToUtf8(int *codepoints, int length)
|
||||||
|
|
||||||
for (int i = 0, bytes = 0; i < length; i++)
|
for (int i = 0, bytes = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
utf8 = CodepointToUtf8(codepoints[i], &bytes);
|
utf8 = CodepointToUTF8(codepoints[i], &bytes);
|
||||||
memcpy(text + size, utf8, bytes);
|
memcpy(text + size, utf8, bytes);
|
||||||
size += bytes;
|
size += bytes;
|
||||||
}
|
}
|
||||||
|
|
@ -1526,7 +1428,8 @@ char *TextToUtf8(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)
|
||||||
RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength)
|
// NOTE: It uses a static array to store UTF-8 bytes
|
||||||
|
RLAPI const char *CodepointToUTF8(int codepoint, int *byteLength)
|
||||||
{
|
{
|
||||||
static char utf8[6] = { 0 };
|
static char utf8[6] = { 0 };
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
|
@ -1563,7 +1466,7 @@ RLAPI const char *CodepointToUtf8(int codepoint, int *byteLength)
|
||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all codepoints from a UTF8 text string, codepoints count returned by parameter
|
// Load all codepoints from a UTF-8 text string, codepoints count returned by parameter
|
||||||
int *LoadCodepoints(const char *text, int *count)
|
int *LoadCodepoints(const char *text, int *count)
|
||||||
{
|
{
|
||||||
int textLength = TextLength(text);
|
int textLength = TextLength(text);
|
||||||
|
|
@ -1595,8 +1498,8 @@ void UnloadCodepoints(int *codepoints)
|
||||||
RL_FREE(codepoints);
|
RL_FREE(codepoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get total number of characters(codepoints) in a UTF8 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 UTF8 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 GetCodepointsCount(const char *text)
|
||||||
{
|
{
|
||||||
unsigned int len = 0;
|
unsigned int len = 0;
|
||||||
|
|
@ -1617,8 +1520,8 @@ int GetCodepointsCount(const char *text)
|
||||||
}
|
}
|
||||||
#endif // SUPPORT_TEXT_MANIPULATION
|
#endif // SUPPORT_TEXT_MANIPULATION
|
||||||
|
|
||||||
// Get next codepoint in a UTF8 encoded text, scanning until '\0' is found
|
// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found
|
||||||
// When a invalid UTF8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
|
// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned
|
||||||
// Total number of bytes processed are returned as a parameter
|
// Total number of bytes processed are returned as a parameter
|
||||||
// NOTE: the standard says U+FFFD should be returned in case of errors
|
// NOTE: the standard says U+FFFD should be returned in case of errors
|
||||||
// but that character is not supported by the default font in raylib
|
// but that character is not supported by the default font in raylib
|
||||||
|
|
@ -1626,7 +1529,7 @@ int GetCodepointsCount(const char *text)
|
||||||
int GetCodepoint(const char *text, int *bytesProcessed)
|
int GetCodepoint(const char *text, int *bytesProcessed)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
UTF8 specs from https://www.ietf.org/rfc/rfc3629.txt
|
UTF-8 specs from https://www.ietf.org/rfc/rfc3629.txt
|
||||||
|
|
||||||
Char. number range | UTF-8 octet sequence
|
Char. number range | UTF-8 octet sequence
|
||||||
(hexadecimal) | (binary)
|
(hexadecimal) | (binary)
|
||||||
|
|
@ -1845,7 +1748,7 @@ static Font LoadBMFont(const char *fileName)
|
||||||
font.baseSize = fontSize;
|
font.baseSize = fontSize;
|
||||||
font.charsCount = charsCount;
|
font.charsCount = charsCount;
|
||||||
font.charsPadding = 0;
|
font.charsPadding = 0;
|
||||||
font.chars = (CharInfo *)RL_MALLOC(charsCount*sizeof(CharInfo));
|
font.chars = (GlyphInfo *)RL_MALLOC(charsCount*sizeof(GlyphInfo));
|
||||||
font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
|
font.recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
|
||||||
|
|
||||||
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#ifdef __cplusplus
|
//...
|
||||||
extern "C" { // Prevents name mangling of functions
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
|
|
@ -67,6 +65,10 @@ extern "C" { // Prevents name mangling of functions
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#if defined(PLATFORM_ANDROID)
|
||||||
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app
|
void InitAssetManager(AAssetManager *manager, const char *dataPath); // Initialize asset manager from android app
|
||||||
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
|
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() -> Read-only!
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user