diff options
| -rw-r--r-- | build.zig | 1 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/scenes/mainMenu.c | 3 | ||||
| -rw-r--r-- | src/scenes/puzzleScene.c | 19 | ||||
| -rw-r--r-- | src/ui_elements/TextEditor.c | 118 | ||||
| -rw-r--r-- | src/ui_elements/UI.h | 32 |
6 files changed, 166 insertions, 8 deletions
@@ -15,6 +15,7 @@ pub fn build(b: *std.Build) void { "src/main.c", "src/resources/resources.c", "src/ui_elements/UI.c", + "src/ui_elements/TextEditor.c", "src/scenes/sceneManager.c", "src/scenes/mainMenu.c", "src/scenes/puzzleScene.c", @@ -4,7 +4,6 @@ #include "resources/resources.h" int main(void) { - if (!InitSceneStack()) { printf("Failed to create a scene stack\n"); return 1; diff --git a/src/scenes/mainMenu.c b/src/scenes/mainMenu.c index 31b52c0..7732f6d 100644 --- a/src/scenes/mainMenu.c +++ b/src/scenes/mainMenu.c @@ -1,13 +1,14 @@ #include <raylib.h> #include <stdlib.h> #include "scenes.h" +#include "../resources/resources.h" bool updateMainMenu(void *self) { return true; } bool drawMainMenu(void *self) { - ClearBackground(SKYBLUE); + DrawBackground(); DrawText("Main menu", 0, 0, 100, BLACK); return true; } diff --git a/src/scenes/puzzleScene.c b/src/scenes/puzzleScene.c index 70a3667..fb45c02 100644 --- a/src/scenes/puzzleScene.c +++ b/src/scenes/puzzleScene.c @@ -6,14 +6,10 @@ typedef struct { Puzzle *PuzzlePtr; + TextArea *EditorInfo; int scroll; } puzzleSceneData; - -bool updatePuzzleScene(void *self) { - return true; -} - const int HEADER_FONT_SIZE = 50; const int PADDING = 10; const int BORDER = 2; @@ -77,13 +73,23 @@ bool drawPuzzleScene(void *self) { DrawTextInRec(pane1, data->PuzzlePtr->Description, GetMainFont(), 20, COLORSCHEME_BROWN, 3, &data->scroll); + DrawTextArea(data->EditorInfo, pane2, GetMainFont(), 20, 2); + + return true; +} + +bool updatePuzzleScene(void *self) { + puzzleSceneData *data = ((Scene *)self)->data; + HandleKeyboard(data->EditorInfo); return true; } void deinitPuzzleScene(void *self) { + puzzleSceneData *data = ((Scene *)self)->data; TraceLog(LOG_INFO, "Deleting a puzzle scene"); - free((puzzleSceneData *)((Scene *)self)->data); + FreeTextArea(data->EditorInfo); + free(data); free((Scene *)self); } @@ -95,6 +101,7 @@ Scene *CreatePuzzleScene(Puzzle *puzzle) { puzzleSceneData *data = malloc(sizeof(puzzleSceneData)); data->PuzzlePtr = puzzle; + data->EditorInfo = CreateTextArea(); outp->data = data; return outp; diff --git a/src/ui_elements/TextEditor.c b/src/ui_elements/TextEditor.c new file mode 100644 index 0000000..ca2d270 --- /dev/null +++ b/src/ui_elements/TextEditor.c @@ -0,0 +1,118 @@ +#include "UI.h" +#include "../resources/resources.h" +#include <raylib.h> +#include <stdlib.h> +#include <string.h> + +void HighlightCharacter(Vector2 lineStartPos, char *line, int index, Font *font, int height, int spacing) { + float x_position = 0; + for (int i = 0; i < index; i++) { + x_position += MeasureChar(font, height, line[i]); + x_position += spacing; + } + DrawLine(lineStartPos.x + x_position, lineStartPos.y, + lineStartPos.x + x_position, lineStartPos.y + height, COLORSCHEME_ORANGE); +} + +TextNode *CreateNode(TextNode *prev, TextNode *next) { + TextNode *node = malloc(sizeof(TextNode)); + if (node == NULL) return NULL; + node->NextNode = next; + node->PrevNode = prev; + node->text = malloc(DEFAULT_TEXT_NODE_SIZE); + if (node->text != NULL) node->cap = DEFAULT_TEXT_NODE_SIZE; + return node; +} + +/// Recursively frees the nodes +void FreeNodeRec(TextNode *node) { + if (node == NULL) return; + FreeNodeRec(node->NextNode); + free(node->text); + free(node); +} + +TextArea *CreateTextArea() { + TextArea *outp = malloc(sizeof(TextArea)); + if (outp == NULL) return NULL; + + TextNode *start_node = CreateNode(NULL, NULL); + if (start_node == NULL) { + free(outp); + return NULL; + } + + outp->StartNode = start_node; + outp->CurrentNode = start_node; + outp->NodeLenth = 1; + return outp; +} + +void FreeTextArea(TextArea *ta) { + FreeNodeRec(ta->StartNode); + free(ta); +} + +/// draws a text area on the screen. Main draw entry point +void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing) { + Vector2 pos = { .x = rec.x, .y = rec.y }; + TextNode *node = ta->StartNode; + while (node != NULL) { + DrawTextEx(*font, node->text, pos, height, spacing, COLORSCHEME_BROWN); + if (node == ta->CurrentNode) + HighlightCharacter(pos, node->text, ta->CursorPosition.x, font, height, spacing); + node = node->NextNode; + pos.x += height; + } +} + +void MoveCursorRight(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + ta->CursorPosition.x += 1; +} + +void MoveCursorLeft(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + ta->CursorPosition.x -= 1; + if (ta->CursorPosition.x < 0) ta->CursorPosition.x = 0; +} + +void InsertChar(TextArea *ta, char new_char) { + if (ta == NULL || ta->CurrentNode == NULL) return; + (ta->CurrentNode->text)[(int)ta->CursorPosition.x] = new_char; + ta->CursorPosition.x += 1; + size_t line_len = strlen(ta->CurrentNode->text); + if (ta->CursorPosition.x > line_len) ta->CursorPosition.x = line_len; +} + +void DeleteChar(TextArea *ta) { + if (ta == NULL || ta->CurrentNode == NULL) return; + if (ta->CursorPosition.x == 0) return; + size_t line_len = strlen(ta->CurrentNode->text); + + if (ta->CursorPosition.x == line_len) { + ta->CurrentNode->text[line_len - 1] = 0x0; + } else { + char *after_str = (ta->CurrentNode->text + (int)ta->CursorPosition.x); + strcpy(ta->CurrentNode->text + (int)ta->CursorPosition.x - 1, after_str); + } + ta->CursorPosition.x -= 1; +} + +bool IsKeyPressedFix(int key) { + return IsKeyPressedRepeat(key) || IsKeyPressed(key); +} + +void HandleKeyboard(TextArea *ta) { + int charKey = GetCharPressed(); + while (charKey > 0) { + if (charKey >= 32 && charKey <= 125) { + InsertChar(ta, (char)charKey); + } + charKey = GetCharPressed(); + } + + if (IsKeyPressedFix(KEY_BACKSPACE)) DeleteChar(ta); + if (IsKeyPressedFix(KEY_LEFT)) MoveCursorLeft(ta); + if (IsKeyPressedFix(KEY_RIGHT)) MoveCursorRight(ta); +} diff --git a/src/ui_elements/UI.h b/src/ui_elements/UI.h index 5868efe..4c94bf7 100644 --- a/src/ui_elements/UI.h +++ b/src/ui_elements/UI.h @@ -1,9 +1,41 @@ #include <raylib.h> +#include <stddef.h> #ifndef UI_ELEMENTS_H #define UI_ELEMENTS_H void DrawRecBordered(Rectangle rec, Color bg, Color border_color, int border_width); void DrawTextInRec(Rectangle rec, char *text, Font *font, int height, Color color, float padding, int *scroll); +float MeasureChar(Font *font, int height, char symbol); + +// ========== TEXT EDITOR ========== + +static const size_t DEFAULT_TEXT_NODE_SIZE = 256; + +typedef struct { + void *PrevNode; + void *NextNode; + char *text; + size_t cap; +} TextNode; + +typedef struct { + TextNode *StartNode; + /// For the quick access + TextNode *CurrentNode; + size_t NodeLenth; + + Vector2 CursorPosition; +} TextArea; + +TextArea *CreateTextArea(); +void FreeTextArea(TextArea *ta); +void DrawTextArea(TextArea *ta, Rectangle rec, Font *font, int height, int spacing); +void InsertChar(TextArea *ta, char new_char); +void DeleteChar(TextArea *ta); + +void HandleKeyboard(TextArea *ta); +void MoveCursorRight(TextArea *ta); +void MoveCursorLeft(TextArea *ta); #endif // UI_ELEMENTS_H |
