From 378d42a0aa53a7c99ad8e624badb94b947461f2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Tue, 13 Sep 2022 12:07:40 +0000 Subject: [PATCH] renderer: draw floating-point text --- code/game/src/renderer_v0.c | 2 +- code/game/src/utils/raylib_helpers.h | 75 ++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/code/game/src/renderer_v0.c b/code/game/src/renderer_v0.c index c15d310..4dc041e 100644 --- a/code/game/src/renderer_v0.c +++ b/code/game/src/renderer_v0.c @@ -79,7 +79,7 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) { DrawTexturePro(GetSpriteTexture2D(assets_find(it_kind)), ASSET_SRC_RECT(), ((Rectangle){ix, iy, 32, 32}), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE)); if (!inv_is_open) - DrawTextEco(zpl_bprintf("%d", qty), ix+24, iy+24, 8, RAYWHITE, 0.0f); + DrawTextEco(zpl_bprintf("%d", qty), x+24, y+24, 8, RAYWHITE, 0.0f); } } }break; diff --git a/code/game/src/utils/raylib_helpers.h b/code/game/src/utils/raylib_helpers.h index 88b90ae..713c3fb 100644 --- a/code/game/src/utils/raylib_helpers.h +++ b/code/game/src/utils/raylib_helpers.h @@ -9,17 +9,86 @@ static inline float lerp(float a, float b, float t) { return a * (1.0f - t) + b * t; } +static inline +void DrawTextCodepointEco(Font font, int codepoint, Vector2 position, float fontSize, Color tint) +{ + // Character index position in sprite font + // NOTE: In case a codepoint is not available in the font, index returned points to '?' + int index = GetGlyphIndex(font, codepoint); + float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor + + // Character destination rectangle on screen + // NOTE: We consider glyphPadding on drawing + Rectangle dstRec = { position.x + font.glyphs[index].offsetX*scaleFactor - (float)font.glyphPadding*scaleFactor, + position.y + font.glyphs[index].offsetY*scaleFactor - (float)font.glyphPadding*scaleFactor, + (font.recs[index].width + 2.0f*font.glyphPadding)*scaleFactor, + (font.recs[index].height + 2.0f*font.glyphPadding)*scaleFactor }; + + // Character source rectangle from font texture atlas + // NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects + Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding, + font.recs[index].width + 2.0f*font.glyphPadding, font.recs[index].height + 2.0f*font.glyphPadding }; + + // Draw the character texture on the screen + DrawTexturePro(font.texture, srcRec, dstRec, (Vector2){ 0, 0 }, 0.0f, tint); +} + +static inline +void DrawTextExEco(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint) +{ + if (font.texture.id == 0) font = GetFontDefault(); // Security check in case of not valid font + + int size = TextLength(text); // Total size in bytes of the text, scanned by codepoints in loop + + int textOffsetY = 0; // Offset between lines (on line break '\n') + float textOffsetX = 0.0f; // Offset X to next character to draw + + float scaleFactor = fontSize/font.baseSize; // Character quad scaling factor + + for (int i = 0; i < size;) + { + // 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; + + if (codepoint == '\n') + { + // NOTE: Fixed line spacing of 1.5 line-height + // TODO: Support custom line spacing defined by user + textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor); + textOffsetX = 0.0f; + } + else + { + if ((codepoint != ' ') && (codepoint != '\t')) + { + DrawTextCodepointEco(font, codepoint, (Vector2){ position.x + textOffsetX, position.y + textOffsetY }, fontSize, tint); + } + + if (font.glyphs[index].advanceX == 0) textOffsetX += ((float)font.recs[index].width*scaleFactor + spacing); + else textOffsetX += ((float)font.glyphs[index].advanceX*scaleFactor + spacing); + } + + i += codepointByteCount; // Move text bytes counter to next codepoint + } +} + static inline void DrawTextEco(const char *text, float posX, float posY, int fontSize, Color color, float spacing) { #if 1 // Check if default font has been loaded if (GetFontDefault().texture.id != 0) { - Vector2 position = { (float)posX , (float)posY }; + Vector2 position = { posX , posY }; float defaultFontSize = 10.0; // Default Font chars height in pixel - float new_spacing = spacing == 0.0f ? (float)fontSize/defaultFontSize : spacing; + float new_spacing = spacing == 0.0f ? fontSize/(float)defaultFontSize : spacing; - DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , color); + DrawTextExEco(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , color); } #endif }