diff options
| author | physick <mynameisgennadiy@vk.com> | 2026-08-30 16:14:59 +0500 |
|---|---|---|
| committer | physick <mynameisgennadiy@vk.com> | 2026-08-30 16:14:59 +0500 |
| commit | 1e7ec08dc9c62df43940d00c1fae4a6e54464b86 (patch) | |
| tree | ee4f3170153fd4dc88feb35b13d541e910780711 | |
| parent | 935ed0235d0454cd18559fb0f6ee58e0647723fd (diff) | |
puzzle collection rewrite
| -rw-r--r-- | build.zig | 1 | ||||
| -rw-r--r-- | src/main.c | 20 | ||||
| -rw-r--r-- | src/puzzles/collection.c | 126 | ||||
| -rw-r--r-- | src/puzzles/puzzle.h | 18 | ||||
| -rw-r--r-- | src/scenes/collectionScene.c | 68 | ||||
| -rw-r--r-- | src/scenes/scenes.h | 2 |
6 files changed, 164 insertions, 71 deletions
@@ -22,6 +22,7 @@ const common_c_files = &[_][]const u8 { "src/puzzles/puzzle.c", "src/puzzles/parser.c", "src/puzzles/distractions.c", + "src/puzzles/collection.c", }; pub fn build(b: *std.Build) void { @@ -4,6 +4,12 @@ #include "resources/resources.h" int main(void) { + CollectionElement el = { + .path = "puzzles", + .type = COLLECTION_ELEMENT_COLLECTION, + .IsInitialized = false, + }; + Puzzle *puzzle = ReadPuzzleFromFile("puzzles/test.pz"); PrintPuzzle(puzzle); @@ -21,15 +27,15 @@ int main(void) { return 1; } - // if (!AddScene(CreatePuzzleCollectionScene("puzzles"))) { - // printf("Failed to create a collection scene\n"); - // return 1; - // } - - if (!AddScene(CreatePuzzleScene(puzzle))) { - printf("Failed to create a puzzle menu\n"); + if (!AddScene(CreatePuzzleCollectionScene("puzzles", &el))) { + printf("Failed to create a collection scene\n"); return 1; } + + // if (!AddScene(CreatePuzzleScene(puzzle))) { + // printf("Failed to create a puzzle menu\n"); + // return 1; + // } SetConfigFlags(FLAG_WINDOW_RESIZABLE); InitWindow(800, 600, "Programming game"); diff --git a/src/puzzles/collection.c b/src/puzzles/collection.c new file mode 100644 index 0000000..bb95eba --- /dev/null +++ b/src/puzzles/collection.c @@ -0,0 +1,126 @@ +#include <dirent.h> +#include "puzzle.h" +#include <raylib.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include "../utils/arena.h" +#include <string.h> + +static const char *IMAGE_NAME = "icon.png"; + +CollectionElementType getTypeFromPath(char *fullPath) { + struct stat st; + if (stat(fullPath, &st) != 0) return COLLECTION_ELEMENT_UNKNOWN; + + if (S_ISDIR(st.st_mode)) { + return COLLECTION_ELEMENT_COLLECTION; + } else if (S_ISREG(st.st_mode)) { + return COLLECTION_ELEMENT_PUZZLE; + } + return COLLECTION_ELEMENT_UNKNOWN; +} + +bool isIcon(struct dirent *entry) { + return strncmp(entry->d_name, IMAGE_NAME, strlen(IMAGE_NAME)) == 0; +} + +void addIcon(CollectionElement *el, struct dirent *entry) { + if (el == NULL || entry == NULL) return; + char fullPath[1024]; +} + +bool isElement(struct dirent *entry, char *basePath) { + if (entry == NULL) return false; + if (strncmp(".", entry->d_name, 1) == 0) return false; + if (isIcon(entry)) return false; + + char full_path_buf[1024]; + snprintf(full_path_buf, sizeof(full_path_buf), "%s/%s", basePath, entry->d_name); + struct stat st; + if (stat(full_path_buf, &st) != 0) return false; + if (S_ISDIR(st.st_mode)) return true; + + size_t entry_name_len = strlen(entry->d_name); + if (entry_name_len < 4) return false; + char *last_bytes = entry->d_name + entry_name_len - 3; + if (strncmp(last_bytes, ".pz", 3) != 0) return false; + + return true; +} + +size_t getElementCount(DIR *dir, CollectionElement *el) { + struct dirent *entry; + size_t outp = 0; + while ((entry = readdir(dir)) != NULL) { + if (isElement(entry, el->path)) outp += 1; + } + rewinddir(dir); + return outp; +} + +void initCollectionFromDir(CollectionElement *el) { + if (el == NULL) return; + + TraceLog(LOG_INFO, "Initializing a collection element from %s/", el->path); + DIR *dir = opendir(el->path); + if (dir == NULL) { + TraceLog(LOG_ERROR, "Failed to open the directory"); + return; + } + + el->childCount = getElementCount(dir, el); + el->children = malloc(sizeof(CollectionElement) * el->childCount); + // printf("element count: %zu\n", el->childCount); + if (el->children == NULL) { + TraceLog(LOG_ERROR, "Failed to allocate the collection element children array"); + closedir(dir); + return; + } + + struct dirent *entry; + char full_path_buf[1024]; + size_t idx = 0; + + while ((entry = readdir(dir)) != NULL) { + if (isIcon(entry)) { + addIcon(el, entry); + continue; + } + if (!isElement(entry, el->path)) continue; + snprintf(full_path_buf, sizeof(full_path_buf), "%s/%s", el->path, entry->d_name); + + struct stat st; + if (stat(full_path_buf, &st) != 0) continue; + + CollectionElement *read_el = &el->children[idx]; + // printf("idx = %zu\n", idx); + if (S_ISDIR(st.st_mode)) { + read_el->type = COLLECTION_ELEMENT_COLLECTION; + } else if (S_ISREG(st.st_mode)) { + read_el->type = COLLECTION_ELEMENT_PUZZLE; + } + read_el->IsInitialized = false; + read_el->path = strdup(full_path_buf); + + idx += 1; + } + + closedir(dir); +} + +void InitializeCollection(CollectionElement *el) { + if (el == NULL) { + TraceLog(LOG_ERROR, "Failed to initialize collection element: the element is NULL"); + return; + } + switch (el->type) { + case COLLECTION_ELEMENT_PUZZLE: break; + case COLLECTION_ELEMENT_COLLECTION: + initCollectionFromDir(el); + break; + default: + TraceLog(LOG_WARNING, "Invalid CollectionElement type"); + break; + } +} diff --git a/src/puzzles/puzzle.h b/src/puzzles/puzzle.h index e8180e1..90ee160 100644 --- a/src/puzzles/puzzle.h +++ b/src/puzzles/puzzle.h @@ -1,5 +1,6 @@ #include <stddef.h> #include <wren.h> +#include <raylib.h> #ifndef PUZZLE_H #define PUZZLE_H @@ -92,4 +93,21 @@ typedef struct { DistractionPuzzle *GetRandomDistraction(); void FreeDistrationPuzzle(DistractionPuzzle *puzzle); +typedef enum { + COLLECTION_ELEMENT_PUZZLE, + COLLECTION_ELEMENT_COLLECTION, + COLLECTION_ELEMENT_UNKNOWN +} CollectionElementType; + +typedef struct CollectionElement { + char *path; + struct CollectionElement *children; + size_t childCount; + Texture2D *icon; + bool IsInitialized; + CollectionElementType type; +} CollectionElement; + +void InitializeCollection(CollectionElement *el); + #endif // PUZZLE_H diff --git a/src/scenes/collectionScene.c b/src/scenes/collectionScene.c index 8ed545a..2a9fc22 100644 --- a/src/scenes/collectionScene.c +++ b/src/scenes/collectionScene.c @@ -9,10 +9,6 @@ #include "../resources/resources.h" #include "../utils/arena.h" -typedef struct { - char *Name; -} CollectionElement; - static const size_t ARENA_SIZE = 1024 * 64; typedef struct { @@ -20,61 +16,10 @@ typedef struct { char *DirPath; char *Name; - CollectionElement *elements; + CollectionElement *collection; 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; } @@ -120,7 +65,7 @@ void deinitCollectionScene(void *self) { free((Scene *)self); } -Scene *CreatePuzzleCollectionScene(char *path) { +Scene *CreatePuzzleCollectionScene(char *path, CollectionElement *el) { TraceLog(LOG_INFO, "Creating a collection scene"); Scene *outp = malloc(sizeof(Scene)); if (outp == NULL) return NULL; @@ -138,12 +83,9 @@ Scene *CreatePuzzleCollectionScene(char *path) { 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); - } + + if (!el->IsInitialized) InitializeCollection(el); + data->collection = el; outp->data = data; diff --git a/src/scenes/scenes.h b/src/scenes/scenes.h index 828f2f3..659dcfd 100644 --- a/src/scenes/scenes.h +++ b/src/scenes/scenes.h @@ -33,6 +33,6 @@ Scene *CreatePuzzleScene(Puzzle *puzzle); Scene *CreateDistractionScene(DistractionPuzzle *puzzle, void (*addTime)(Scene *, size_t)); Scene *CreateResultView(SubmitionResult *result); -Scene *CreatePuzzleCollectionScene(char *path); +Scene *CreatePuzzleCollectionScene(char *path, CollectionElement *el); #endif // SCENES_H |
