Explorar o código

Add size vars in the textbox

Evgeniy Parfenyuk hai 2 meses
pai
achega
af8ddd19e2

+ 3 - 1
Makefile

@@ -1,7 +1,7 @@
 # Compiler and flags
 CC = gcc
 CFLAGS = -Wall -Wextra -Wpedantic -Werror -std=c99 \
-	     -O2 -Iexternal/raylib/src
+	     -O2 -Iexternal/raylib/src -MMD -MP
 LDFLAGS = -Lexternal/raylib/ -lraylib -lm -lpthread
 
 # Directories
@@ -75,3 +75,5 @@ clean:
 
 # Phony targets
 .PHONY: all clean run raylib
+
+-include $(OBJECTS:.o=.d)

+ 93 - 0
assets/balsamiq_sans/LICENSE.txt

@@ -0,0 +1,93 @@
+Copyright 2011 The Balsamiq Sans Project Authors (https://github.com/balsamiq/balsamiqsans)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded, 
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.

BIN=BIN
assets/balsamiq_sans/bold.ttf


BIN=BIN
assets/balsamiq_sans/bold_italic.ttf


BIN=BIN
assets/balsamiq_sans/italic.ttf


BIN=BIN
assets/balsamiq_sans/regular.ttf


+ 21 - 2
src/main.c

@@ -20,6 +20,8 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #include <raylib.h>
 #include <string.h>
 
+#include "parser.h"
+
 typedef struct {
     Texture2D img;
     Vector2 pos; // In percents
@@ -31,8 +33,11 @@ typedef struct {
 
     char *name;
     Color name_color;
+    int name_size;
+
     char *text;
     Color text_color;
+    int text_size;
 } GameState;
 
 
@@ -42,6 +47,7 @@ int main(void)
     const int screenHeight = 1080;
 
     SetConfigFlags(FLAG_FULLSCREEN_MODE);
+    SetTraceLogLevel(LOG_ERROR);
     InitWindow(screenWidth, screenHeight,
                "Vinora Engine");
 
@@ -50,6 +56,11 @@ int main(void)
 
     cur_state.name = "Sumi";
     cur_state.name_color = RAYWHITE;
+    cur_state.name_size = 40;
+
+    cur_state.text = "Hello, World!";
+    cur_state.text_color = RAYWHITE;
+    cur_state.text_size = 30;
 
     cur_state.layers[0].img = LoadTexture("assets/spiral_atlas/bedroom.jpg");
     cur_state.layers[0].pos = (Vector2){0.5, 0.5};
@@ -70,9 +81,17 @@ int main(void)
                                     cur_state.layers[i].img.height / 2,
                             RAYWHITE);
             }
+            DrawRectangle(screenWidth/10, screenHeight/5 * 4 - 10,
+                          screenWidth * 4 / 5, screenHeight / 5,
+                          (Color){0, 0, 0, 150});
             DrawText(cur_state.name, screenWidth/2  -
-            (strlen(cur_state.name)*40/2)/2, screenHeight/5*4 - 40, 40,
-            cur_state.name_color);
+                (strlen(cur_state.name)*cur_state.name_size/2)/2,
+                screenHeight/5*4,
+                cur_state.name_size, cur_state.name_color);
+            DrawText(cur_state.text, screenWidth/2  -
+                (strlen(cur_state.text)*cur_state.text_size/2)/2,
+                screenHeight/5*4.5,
+                cur_state.text_size, cur_state.text_color);
             DrawFPS(5, 5);
 
         EndDrawing();

+ 27 - 0
src/parser.h

@@ -0,0 +1,27 @@
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUF_SIZE 512 // Max size according to specification
+
+char *read_chunk_from_file(char *filename)
+{
+    FILE *fp;
+    if ((fp = fopen(filename, "r")) == NULL) {
+        perror(filename);
+        return NULL;
+    }
+
+    char *result = malloc(BUF_SIZE);
+
+    if (fgets(result, BUF_SIZE, fp) != NULL) { 
+        result[strlen(result) - 1] = 'X';
+    }
+        
+
+    return result;
+}
+
+#endif // PARSER_H

+ 152 - 0
src/raytext.h

@@ -0,0 +1,152 @@
+/*
+raytext.h -- advanced text functions for raylib.
+
+Copyright (c) 2025-2026 Evgeniy "Parthen" Parfenyuk <parthen [at] riseup.net>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#ifndef RAYTEXT_H
+#define RAYTEXT_H
+
+// From raylib examples, TODO: re-write 
+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
+    }
+}
+#endif

+ 9 - 0
src/text_utils.h

@@ -29,5 +29,14 @@ inline bool is_whitespace(int ch)
             ch == '\r' || ch == '\v' || ch == '\f');
 }
 
+inline bool is_emptyline(char *line)
+{
+    for (size_t i = 0; i < strlen(line); i++)
+        if (!is_whitespace(line[i]))
+            return false;
+
+    return true;
+}
+
 
 #endif