#include #include #include #include #include #include #include "scenes.h" #include "../ui_elements/UI.h" #include "../resources/resources.h" #include "../utils/arena.h" typedef struct { char *Name; } CollectionElement; static const size_t ARENA_SIZE = 1024 * 64; typedef struct { Arena arena; char *DirPath; char *Name; CollectionElement *elements; size_t count; } CollectionSceneData; bool readCollectionFromDir(char *path, CollectionSceneData *data) { DIR *dir = opendir(path); if (dir == NULL) { perror("Failed to open a dir"); return false; } CollectionElement *outp = malloc(sizeof(CollectionElement)); if (outp == NULL) { TraceLog(LOG_ERROR, "Failed to create the buffer in the heap"); closedir(dir); return false; }; struct dirent *entry; size_t cap = 16; CollectionElement *elements = malloc(sizeof(CollectionElement) * cap); while ((entry = readdir(dir)) != NULL) { // The element is not a file. Also eliminates `.` and `..` if (entry->d_type != 8) continue; if (data->count == cap) { CollectionElement *new = realloc(elements, cap * 2); if (new == NULL) break; cap *= 2; elements = new; } CollectionElement *current = &elements[data->count]; current->Name = ArenaStrdup(&data->arena, entry->d_name); data->count += 1; } // Moving all of this to the arena size_t array_size = sizeof(CollectionElement) * data->count; data->elements = ArenaAlloc(&data->arena, array_size); if (data->elements == NULL) { TraceLog(LOG_ERROR, "The arena failed to allocate the element array"); // The arena is full free(elements); data->count = 0; closedir(dir); return false; } memcpy(data->elements, elements, array_size); free(elements); closedir(dir); return true; } CollectionSceneData *getData(void *self) { return ((Scene *)self)->data; } void DrawCollectionName(char *name) { Vector2 width = MeasureTextEx(*GetMainFont(), name, 50, 1); int screen_width = GetScreenWidth(); Vector2 pos = { .y = 20, .x = (screen_width - width.x) / 2, }; DrawTextEx(*GetMainFont(), name, pos, HEADER_FONT_SIZE, 1, COLORSCHEME_BROWN); } // Does not allocate the memory char *getCollectionName(char *path) { char *outp = path; size_t len = strlen(path); for (size_t i = 0; i < len; ++i) { if ((path[i] == '/' || path[i] == '\\') && path[i+1] != 0x0) { outp = path + i + 1; } } return outp; } bool updateCollectionScene(void *self) { return true; } bool drawCollectionScene(void *self) { CollectionSceneData *data = getData(self); DrawBackground(); DrawCollectionName(data->Name); DrawPageView(GetScreenHeight() - 60, 5, 2); return true; } void deinitCollectionScene(void *self) { TraceLog(LOG_INFO, "Deleting a collection scene"); CollectionSceneData *data = getData(self); if (data != NULL) { free(data->arena.mem); free(data); } free((Scene *)self); } Scene *CreatePuzzleCollectionScene(char *path) { TraceLog(LOG_INFO, "Creating a collection scene"); Scene *outp = malloc(sizeof(Scene)); if (outp == NULL) return NULL; outp->Update = updateCollectionScene; outp->Draw = drawCollectionScene; outp->Deint = deinitCollectionScene; outp->IsTransparent = false; CollectionSceneData *data = malloc(sizeof(CollectionSceneData)); if (data == NULL) { free(outp); return NULL; } data->arena = (Arena){0}; ArenaInit(&data->arena, ARENA_SIZE); data->DirPath = ArenaStrdup(&data->arena, path); data->Name = getCollectionName(path); if (!readCollectionFromDir(path, data)) { TraceLog(LOG_ERROR, "Failed to read the collection directory"); } for (int i = 0; i < data->count; i++) { TraceLog(LOG_INFO, "Puzzle: %s", data->elements[i].Name); } outp->data = data; return outp; }