comparison libmlk-rpg/mlk/rpg/tileset-loader-file.c @ 593:f9e85d0aca74

rpg: introduce private loader_file to help allocating map/tileset The structure is just an allocator and owner for various data shared among the map and the tileset such as sprites, textures, animations... While here, simplify use of mlk_(map|tileset)_loader_file so they don't have a public structure anymore but insert themselves into the loader->data.
author David Demelier <markand@malikania.fr>
date Tue, 21 Mar 2023 14:08:15 +0100
parents ffd972a3d084
children e070fdcc592b
comparison
equal deleted inserted replaced
592:1560ef13146c 593:f9e85d0aca74
23 #include <mlk/core/animation.h> 23 #include <mlk/core/animation.h>
24 #include <mlk/core/image.h> 24 #include <mlk/core/image.h>
25 #include <mlk/core/sprite.h> 25 #include <mlk/core/sprite.h>
26 #include <mlk/core/texture.h> 26 #include <mlk/core/texture.h>
27 27
28 #include "loader-file_p.h"
28 #include "tileset-loader-file.h" 29 #include "tileset-loader-file.h"
29 #include "tileset-loader.h" 30 #include "tileset-loader.h"
30 #include "tileset.h" 31 #include "tileset.h"
31 32
32 static inline void * 33 struct self {
33 allocate(void ***array, size_t width) 34 /* Resources allocator. */
35 struct mlk__loader_file *loader;
36
37 /* Arrays reallocated on purpose. */
38 struct mlk_tileset_collision *tilecollisions;
39 struct mlk_tileset_animation *tileanimations;
40 };
41
42 static struct self *
43 self_new(const char *path)
34 { 44 {
35 void **ptr, *elem; 45 struct self *self;
36 46
37 /* Not yet allocated? Allocate a new pointer element. */ 47 if (!(self = mlk_alloc_new0(1, sizeof (*self))))
38 if (!*array) 48 return NULL;
39 ptr = mlk_alloc_new0(1, sizeof (void *)); 49 if (!(self->loader = mlk__loader_file_new(path))) {
40 else 50 mlk_alloc_free(self);
41 ptr = mlk_alloc_expand(*array, 1); 51 return NULL;
52 }
42 53
43 if (!ptr) 54 return self;
44 return NULL; 55 }
45 56
46 /* Now allocate the element itself because. */ 57 static void
47 if (!(elem = mlk_alloc_new0(1, width))) 58 self_free(struct self *self)
48 return NULL; 59 {
60 mlk__loader_file_free(self->loader);
49 61
50 /* Store it into the array of elements. */ 62 /* Clear array of collisions/animations .*/
51 ptr[mlk_alloc_getn(ptr) - 1] = elem; 63 mlk_alloc_free(self->tilecollisions);
52 *array = ptr; 64 mlk_alloc_free(self->tileanimations);
65 }
53 66
54 return elem;
55 }
56 67
57 static void * 68 static void *
58 expand(void **array, size_t n, size_t w) 69 expand(void **array, size_t n, size_t w)
59 { 70 {
60 void *ptr; 71 void *ptr;
68 *array = ptr; 79 *array = ptr;
69 80
70 return ptr; 81 return ptr;
71 } 82 }
72 83
73 static void 84 static struct mlk_texture *
74 finish(void ***ptr, void (*finish)(void *)) 85 new_texture(struct mlk_tileset_loader *loader, struct mlk_tileset *tileset, const char *ident)
75 { 86 {
76 size_t len; 87 (void)tileset;
77 88
78 /* Already cleared. */ 89 struct self *self = loader->data;
79 if (!*ptr)
80 return;
81 90
82 len = mlk_alloc_getn(*ptr); 91 return mlk__loader_file_texture_open(self->loader, ident);
83
84 for (size_t i = 0; i < len; ++i)
85 finish((*ptr)[i]);
86
87 mlk_alloc_free(*ptr);
88 *ptr = NULL;
89 }
90
91 static void
92 finish_texture(void *element)
93 {
94 mlk_texture_finish(element);
95 mlk_alloc_free(element);
96 }
97
98 static struct mlk_texture *
99 init_texture(struct mlk_tileset_loader *self, const char *ident)
100 {
101 struct mlk_tileset_loader_file *file = self->data;
102 struct mlk_texture *texture;
103 char path[MLK_PATH_MAX];
104
105 snprintf(path, sizeof (path), "%s/%s", file->directory, ident);
106
107 /* No need to deallocate, already done in finish anyway. */
108 if (!(texture = allocate((void ***)&file->textures, sizeof (struct mlk_texture))))
109 return NULL;
110 if (mlk_image_open(texture, path) < 0)
111 return NULL;
112
113 return texture;
114 } 92 }
115 93
116 static struct mlk_sprite * 94 static struct mlk_sprite *
117 init_sprite(struct mlk_tileset_loader *self) 95 new_sprite(struct mlk_tileset_loader *loader, struct mlk_tileset *tileset)
118 { 96 {
119 struct mlk_tileset_loader_file *file = self->data; 97 (void)tileset;
120 98
121 return allocate((void ***)&file->sprites, sizeof (struct mlk_sprite)); 99 struct self *self = loader->data;
100
101 return mlk__loader_file_sprite_new(self->loader);
122 } 102 }
123 103
124 static struct mlk_animation * 104 static struct mlk_animation *
125 init_animation(struct mlk_tileset_loader *self) 105 new_animation(struct mlk_tileset_loader *loader, struct mlk_tileset *tileset)
126 { 106 {
127 struct mlk_tileset_loader_file *file = self->data; 107 (void)tileset;
128 108
129 return allocate((void ***)&file->animations, sizeof (struct mlk_animation)); 109 struct self *self = loader->data;
110
111 return mlk__loader_file_animation_new(self->loader);
130 } 112 }
131 113
132 struct mlk_tileset_collision * 114 struct mlk_tileset_collision *
133 expand_collisions(struct mlk_tileset_loader *self, 115 expand_collisions(struct mlk_tileset_loader *loader,
116 struct mlk_tileset *tileset,
134 struct mlk_tileset_collision *array, 117 struct mlk_tileset_collision *array,
135 size_t arraysz) 118 size_t arraysz)
136 { 119 {
120 (void)tileset;
137 (void)array; 121 (void)array;
138 122
139 struct mlk_tileset_loader_file *file = self->data; 123 struct self *self = loader->data;
140 124
141 return expand((void **)&file->tilecollisions, arraysz, sizeof (struct mlk_tileset_collision)); 125 return expand((void **)&self->tilecollisions, arraysz, sizeof (struct mlk_tileset_collision));
142 } 126 }
143 127
144 struct mlk_tileset_animation * 128 struct mlk_tileset_animation *
145 expand_animations(struct mlk_tileset_loader *self, 129 expand_animations(struct mlk_tileset_loader *loader,
130 struct mlk_tileset *tileset,
146 struct mlk_tileset_animation *array, 131 struct mlk_tileset_animation *array,
147 size_t arraysz) 132 size_t arraysz)
148 { 133 {
134 (void)tileset;
149 (void)array; 135 (void)array;
150 136
151 struct mlk_tileset_loader_file *file = self->data; 137 struct self *self = loader->data;
152 138
153 return expand((void **)&file->tileanimations, arraysz, sizeof (struct mlk_tileset_animation)); 139 return expand((void **)&self->tileanimations, arraysz, sizeof (struct mlk_tileset_animation));
140 }
141
142 int
143 mlk_tileset_loader_file_init(struct mlk_tileset_loader *loader, const char *filename)
144 {
145 assert(loader);
146 assert(filename);
147
148 struct self *self;
149
150 memset(loader, 0, sizeof (*loader));
151
152 if (!(self = self_new(filename)))
153 return -1;
154
155 loader->data = self;
156 loader->new_texture = new_texture;
157 loader->new_sprite = new_sprite;
158 loader->new_animation = new_animation;
159 loader->expand_collisions = expand_collisions;
160 loader->expand_animations = expand_animations;
161
162 return 0;
154 } 163 }
155 164
156 void 165 void
157 mlk_tileset_loader_file_init(struct mlk_tileset_loader_file *file, 166 mlk_tileset_loader_file_finish(struct mlk_tileset_loader *loader)
158 struct mlk_tileset_loader *loader,
159 const char *filename)
160 { 167 {
161 assert(file);
162 assert(loader); 168 assert(loader);
163 assert(filename);
164 169
165 char filepath[MLK_PATH_MAX]; 170 struct self *self = loader->data;
166 171
167 memset(file, 0, sizeof (*file)); 172 if (self)
173 self_free(self);
174
168 memset(loader, 0, sizeof (*loader)); 175 memset(loader, 0, sizeof (*loader));
169
170 /* Determine base filename base directory. */
171 mlk_util_strlcpy(filepath, filename, sizeof (filepath));
172 mlk_util_strlcpy(file->directory, mlk_util_dirname(filepath), sizeof (file->directory));
173
174 loader->data = file;
175 loader->init_texture = init_texture;
176 loader->init_sprite = init_sprite;
177 loader->init_animation = init_animation;
178 loader->expand_collisions = expand_collisions;
179 loader->expand_animations = expand_animations;
180 } 176 }
181
182 void
183 mlk_tileset_loader_file_finish(struct mlk_tileset_loader_file *file)
184 {
185 assert(file);
186
187 /* Finalize individual elements. */
188 finish((void ***)&file->textures, finish_texture);
189 finish((void ***)&file->sprites, mlk_alloc_free);
190 finish((void ***)&file->animations, mlk_alloc_free);
191
192 /* Clear array of collisions/animations .*/
193 mlk_alloc_free(file->tilecollisions);
194 mlk_alloc_free(file->tileanimations);
195
196 memset(file, 0, sizeof (*file));
197 }