1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#include <dirent.h>
#include <raylib.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}
|