diff options
| -rw-r--r-- | API.md | 22 | ||||
| -rw-r--r-- | ReiLua_API.lua | 34 | ||||
| -rw-r--r-- | changelog | 2 | ||||
| -rw-r--r-- | devnotes | 8 | ||||
| -rw-r--r-- | examples/window/main.lua | 2 | ||||
| -rw-r--r-- | include/text.h | 2 | ||||
| -rw-r--r-- | src/lua_core.c | 6 | ||||
| -rw-r--r-- | src/text.c | 184 | ||||
| -rw-r--r-- | src/textures.c | 12 |
9 files changed, 246 insertions, 26 deletions
@@ -2725,10 +2725,14 @@ ColorPicker right hue bar selector overflow ## Globals - LightType > LIGHT_DIRECTIONAL = 0 +Directional light + --- > LIGHT_POINT = 1 +Point light + --- @@ -5618,8 +5622,8 @@ NOTE! Should be TEXTURE_TYPE_TEXTURE. Pixel should be in format { { 255, 255, 25 > RL.UpdateTextureRec( Texture texture, Rectangle rec, int{} pixels ) -Update GPU texture rectangle with new data -NOTE! Should be TEXTURE_TYPE_TEXTURE. Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format +Update GPU texture rectangle with new data. +Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format --- @@ -5891,7 +5895,7 @@ Load font from file with extended parameters, use NULL for fontChars to load the > font = RL.LoadFontFromImage( Image image, Color key, int firstChar ) -Load font from Image ( XNA style) +Load font from Image (XNA style) - Success return Font @@ -5951,6 +5955,18 @@ Draw multiple character (codepoint) --- +> RL.DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint ) + +Draw text using font inside rectangle limits. Function from raylib [text] example - Rectangle bounds + +--- + +> RL.DrawTextBoxedSelectable( Font font, string 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. Function from raylib [text] example - Rectangle bounds + +--- + ## Text - Font info functions --- diff --git a/ReiLua_API.lua b/ReiLua_API.lua index 42ee4fb..269a8a7 100644 --- a/ReiLua_API.lua +++ b/ReiLua_API.lua @@ -900,7 +900,9 @@ RL.HUEBAR_SELECTOR_OVERFLOW=20 -- Globals - LightType +---Directional light RL.LIGHT_DIRECTIONAL=0 +---Point light RL.LIGHT_POINT=1 -- Globals - RLGL @@ -3050,8 +3052,8 @@ function RL.UnloadRenderTexture( target ) end ---@return any RL.UpdateTexture function RL.UpdateTexture( texture, pixels ) end ----Update GPU texture rectangle with new data ----NOTE! Should be TEXTURE_TYPE_TEXTURE. Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format +---Update GPU texture rectangle with new data. +---Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format ---@param texture any ---@param rec table ---@param pixels any @@ -3287,7 +3289,7 @@ function RL.LoadFont( fileName ) end ---@return any font function RL.LoadFontEx( fileName, fontSize, fontChars ) end ----Load font from Image ( XNA style) +---Load font from Image (XNA style) ---- Success return Font ---@param image any ---@param key table @@ -3362,6 +3364,32 @@ function RL.DrawTextCodepoint( font, codepoint, position, fontSize, tint ) end ---@return any RL.DrawTextCodepoints function RL.DrawTextCodepoints( font, codepoints, position, fontSize, spacing, tint ) end +---Draw text using font inside rectangle limits. Function from raylib [text] example - Rectangle bounds +---@param font any +---@param char any +---@param rec table +---@param fontSize number +---@param spacing number +---@param wordWrap boolean +---@param tint table +---@return any RL.DrawTextBoxed +function RL.DrawTextBoxed( font, char, rec, fontSize, spacing, wordWrap, tint ) end + +---Draw text using font inside rectangle limits with support for text selection. Function from raylib [text] example - Rectangle bounds +---@param font any +---@param text string +---@param rec table +---@param fontSize number +---@param spacing number +---@param wordWrap boolean +---@param tint table +---@param selectStart integer +---@param selectLength integer +---@param selectTint table +---@param selectBackTint table +---@return any RL.DrawTextBoxedSelectable +function RL.DrawTextBoxedSelectable( font, text, rec, fontSize, spacing, wordWrap, tint, selectStart, selectLength, selectTint, selectBackTint ) end + -- Text - Font info functions ---Measure string size for Font @@ -34,6 +34,8 @@ DETAILED CHANGES: - ADDED: GetGlyphIndex, GetGlyphInfo and GetGlyphAtlasRec. - ADDED: SetWindowIcons, SetWindowOpacity and GetWindowHandle. - CHANGED: Merged uluaGet*Index functions to uluaGet* functions. + - FIXED: LoadFontEx. + - ADDED: DrawTextBoxed and DrawTextBoxedSelectable From raylib [text] example - Rectangle bounds ------------------------------------------------------------------------ Release: ReiLua version 0.5.0 Using Raylib 4.5 @@ -27,15 +27,7 @@ Bugs { } Needs Testing { - * UpdateTexture - * UpdateTextureRec - * LoadSoundFromWave - * LoadFont - * LoadFontEx - * LoadFontFromImage * UpdateMesh - * LoadModelFromMesh - * RLGL - Matrix state management * rlSetUniform * rlSetShader } diff --git a/examples/window/main.lua b/examples/window/main.lua index 3e10f34..63c18d7 100644 --- a/examples/window/main.lua +++ b/examples/window/main.lua @@ -17,7 +17,7 @@ function RL.process( delta ) end if RL.IsKeyPressed( RL.KEY_SPACE ) then - textColor = RL.BLACK + textColor = RL.RED textPos = { 192, 200 } end end diff --git a/include/text.h b/include/text.h index ddf782e..49b89a0 100644 --- a/include/text.h +++ b/include/text.h @@ -14,6 +14,8 @@ int ltextDrawTextEx( lua_State *L ); int ltextDrawTextPro( lua_State *L ); int ltextDrawTextCodepoint( lua_State *L ); int ltextDrawTextCodepoints( lua_State *L ); +int ltextDrawTextBoxed( lua_State *L ); +int ltextDrawTextBoxedSelectable( lua_State *L ); /* Font info functions. */ int ltextMeasureText( lua_State *L ); int ltextGetGlyphIndex( lua_State *L ); diff --git a/src/lua_core.c b/src/lua_core.c index b07034c..499f2a2 100644 --- a/src/lua_core.c +++ b/src/lua_core.c @@ -774,8 +774,8 @@ static void defineGlobals() { assignGlobalInt( HUEBAR_SELECTOR_HEIGHT, "HUEBAR_SELECTOR_HEIGHT" ); // ColorPicker right hue bar selector height assignGlobalInt( HUEBAR_SELECTOR_OVERFLOW, "HUEBAR_SELECTOR_OVERFLOW" ); // ColorPicker right hue bar selector overflow /* LightType */ - assignGlobalInt( LIGHT_DIRECTIONAL, "LIGHT_DIRECTIONAL" ); - assignGlobalInt( LIGHT_POINT, "LIGHT_POINT" ); + assignGlobalInt( LIGHT_DIRECTIONAL, "LIGHT_DIRECTIONAL" ); // Directional light + assignGlobalInt( LIGHT_POINT, "LIGHT_POINT" ); // Point light /* RLGL Default internal render batch elements limits */ assignGlobalInt( RL_DEFAULT_BATCH_BUFFER_ELEMENTS, "RL_DEFAULT_BATCH_BUFFER_ELEMENTS" ); // Default internal render batch elements limits assignGlobalInt( RL_DEFAULT_BATCH_BUFFERS, "RL_DEFAULT_BATCH_BUFFERS" ); // Default number of batch buffers (multi-buffering) @@ -1945,6 +1945,8 @@ void luaRegister() { assingGlobalFunction( "DrawTextPro", ltextDrawTextPro ); assingGlobalFunction( "DrawTextCodepoint", ltextDrawTextCodepoint ); assingGlobalFunction( "DrawTextCodepoints", ltextDrawTextCodepoints ); + assingGlobalFunction( "DrawTextBoxed", ltextDrawTextBoxed ); + assingGlobalFunction( "DrawTextBoxedSelectable", ltextDrawTextBoxedSelectable ); /* Font info functions. */ assingGlobalFunction( "MeasureText", ltextMeasureText ); assingGlobalFunction( "GetGlyphIndex", ltextGetGlyphIndex ); @@ -4,6 +4,144 @@ #include "textures.h" #include "lua_core.h" +// DrawTextBoxed and DrawTextBoxedSelectable from raylib [text] example - Rectangle bounds + +// Draw text using font inside rectangle limits with support for text selection +static void DrawTextBoxedSelectable(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint, int selectStart, int selectLength, Color selectTint, Color selectBackTint) +{ + 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.glyphs[index].advanceX == 0) ? font.recs[index].width*scaleFactor : font.glyphs[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; + } + } + + if ((textOffsetX != 0) || (codepoint != ' ')) textOffsetX += glyphWidth; // avoid leading spaces + } +} + +// Draw text using font inside rectangle limits +static void DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint) +{ + DrawTextBoxedSelectable(font, text, rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE); +} + /* ## Text - Loading */ @@ -54,8 +192,8 @@ int ltextLoadFontEx( lua_State *L ) { if ( lua_istable( L, 3 ) ) { int glyphCount = uluaGetTableLen( L, 3 ); int fontChars[ glyphCount ]; - - int t = lua_gettop( L ); + + int t = 3; int i = 0; lua_pushnil( L ); @@ -82,7 +220,7 @@ int ltextLoadFontEx( lua_State *L ) { /* > font = RL.LoadFontFromImage( Image image, Color key, int firstChar ) -Load font from Image ( XNA style) +Load font from Image (XNA style) - Success return Font */ @@ -240,6 +378,46 @@ int ltextDrawTextCodepoints( lua_State *L ) { } /* +> RL.DrawTextBoxed(Font font, const char *text, Rectangle rec, float fontSize, float spacing, bool wordWrap, Color tint ) + +Draw text using font inside rectangle limits. Function from raylib [text] example - Rectangle bounds +*/ +int ltextDrawTextBoxed( lua_State *L ) { + Font *font = uluaGetFont( L, 1 ); + Rectangle rec = uluaGetRectangle( L, 3 ); + float fontSize = luaL_checknumber( L, 4 ); + float spacing = luaL_checknumber( L, 5 ); + bool wordWrap = uluaGetBoolean( L, 6 ); + Color tint = uluaGetColor( L, 7 ); + + DrawTextBoxedSelectable( *font, luaL_checkstring( L, 2 ), rec, fontSize, spacing, wordWrap, tint, 0, 0, WHITE, WHITE ); + + return 0; +} + +/* +> RL.DrawTextBoxedSelectable( Font font, string 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. Function from raylib [text] example - Rectangle bounds +*/ +int ltextDrawTextBoxedSelectable( lua_State *L ) { + Font *font = uluaGetFont( L, 1 ); + Rectangle rec = uluaGetRectangle( L, 3 ); + float fontSize = luaL_checknumber( L, 4 ); + float spacing = luaL_checknumber( L, 5 ); + bool wordWrap = uluaGetBoolean( L, 6 ); + Color tint = uluaGetColor( L, 7 ); + int selectStart = luaL_checkinteger( L, 8 ); + int selectLength = luaL_checkinteger( L, 9 ); + Color selectTint = uluaGetColor( L, 10 ); + Color selectBackTint = uluaGetColor( L, 11 ); + + DrawTextBoxedSelectable( *font, luaL_checkstring( L, 2 ), rec, fontSize, spacing, wordWrap, tint, selectStart, selectLength, selectTint, selectBackTint ); + + return 0; +} + +/* ## Text - Font info functions */ diff --git a/src/textures.c b/src/textures.c index cef43f5..f31d4d8 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1123,14 +1123,14 @@ int ltexturesUpdateTexture( lua_State *L ) { unsigned char *pixels = malloc( len * 4 * sizeof( unsigned char ) ); int t = lua_gettop( L ); - int i = 0; + unsigned int i = 0; lua_pushnil( L ); while ( lua_next( L, t ) != 0 ) { size_t colLen = uluaGetTableLen( L, lua_gettop( L ) ); int t2 = lua_gettop( L ); - int j = 0; + unsigned int j = 0; lua_pushnil( L ); while ( lua_next( L, t2 ) != 0 ) { @@ -1151,8 +1151,8 @@ int ltexturesUpdateTexture( lua_State *L ) { /* > RL.UpdateTextureRec( Texture texture, Rectangle rec, int{} pixels ) -Update GPU texture rectangle with new data -NOTE! Should be TEXTURE_TYPE_TEXTURE. Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format +Update GPU texture rectangle with new data. +Pixel should be in format { { 255, 255, 255, 255 }... } depending on the pixel format */ int ltexturesUpdateTextureRec( lua_State *L ) { Texture *texture = uluaGetTexture( L, 1 ); @@ -1162,14 +1162,14 @@ int ltexturesUpdateTextureRec( lua_State *L ) { unsigned char *pixels = malloc( len * 4 * sizeof( unsigned char ) ); int t = lua_gettop( L ); - int i = 0; + unsigned int i = 0; lua_pushnil( L ); while ( lua_next( L, t ) != 0 ) { size_t colLen = uluaGetTableLen( L, lua_gettop( L ) ); int t2 = lua_gettop( L ); - int j = 0; + unsigned int j = 0; lua_pushnil( L ); while ( lua_next( L, t2 ) != 0 ) { |
