1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2014 by Artsoft Entertainment
7 // https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
19 char *source_filename;
22 Bitmap *bitmaps[NUM_IMG_BITMAP_POINTERS];
24 int original_width; // original image file width
25 int original_height; // original image file height
27 boolean contains_small_images; // set after adding small images
28 boolean contains_textures; // set after adding GPU textures
29 boolean scaled_up; // set after scaling up
31 int conf_tile_size; // tile size as defined in config
32 int game_tile_size; // tile size as resized for game
34 char *leveldir; // level set when image was loaded
36 typedef struct ImageInfo ImageInfo;
38 static struct ArtworkListInfo *image_info = NULL;
40 static void *Load_Image(char *filename)
42 ImageInfo *img_info = checked_calloc(sizeof(ImageInfo));
44 if ((img_info->bitmaps[IMG_BITMAP_STANDARD] = LoadImage(filename)) == NULL)
46 Warn("cannot load image file '%s': LoadImage() failed", filename);
53 img_info->source_filename = getStringCopy(filename);
55 img_info->original_width = img_info->bitmaps[IMG_BITMAP_STANDARD]->width;
56 img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
58 img_info->contains_small_images = FALSE;
59 img_info->contains_textures = FALSE;
60 img_info->scaled_up = FALSE;
62 img_info->conf_tile_size = 0; // will be set later
63 img_info->game_tile_size = 0; // will be set later
65 img_info->leveldir = NULL; // will be set later
70 static void FreeImage(void *ptr)
72 ImageInfo *image = (ImageInfo *)ptr;
78 for (i = 0; i < NUM_IMG_BITMAPS; i++)
79 if (image->bitmaps[i])
80 FreeBitmap(image->bitmaps[i]);
82 if (image->source_filename)
83 free(image->source_filename);
88 int getImageListSize(void)
90 return (image_info->num_file_list_entries +
91 image_info->num_dynamic_file_list_entries);
94 struct FileInfo *getImageListEntryFromImageID(int pos)
96 int num_list_entries = image_info->num_file_list_entries;
97 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
99 return (pos < num_list_entries ? &image_info->file_list[list_pos] :
100 &image_info->dynamic_file_list[list_pos]);
103 static ImageInfo *getImageInfoEntryFromImageID(int pos)
105 int num_list_entries = image_info->num_file_list_entries;
106 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
107 ImageInfo **img_info =
108 (ImageInfo **)(pos < num_list_entries ? image_info->artwork_list :
109 image_info->dynamic_artwork_list);
111 return img_info[list_pos];
114 Bitmap **getBitmapsFromImageID(int pos)
116 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
118 return (img_info != NULL ? img_info->bitmaps : NULL);
121 int getOriginalImageWidthFromImageID(int pos)
123 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
125 return (img_info != NULL ? img_info->original_width : 0);
128 int getOriginalImageHeightFromImageID(int pos)
130 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
132 return (img_info != NULL ? img_info->original_height : 0);
135 char *getTokenFromImageID(int graphic)
137 struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
139 return (file_list != NULL ? file_list->token : NULL);
142 int getImageIDFromToken(char *token)
144 struct FileInfo *file_list = image_info->file_list;
145 int num_list_entries = image_info->num_file_list_entries;
148 for (i = 0; i < num_list_entries; i++)
149 if (strEqual(file_list[i].token, token))
155 char *getImageConfigFilename(void)
157 return getCustomArtworkConfigFilename(image_info->type);
160 int getImageListPropertyMappingSize(void)
162 return image_info->num_property_mapping_entries;
165 struct PropertyMapping *getImageListPropertyMapping(void)
167 return image_info->property_mapping;
170 void InitImageList(struct ConfigInfo *config_list, int num_file_list_entries,
171 struct ConfigTypeInfo *config_suffix_list,
172 char **base_prefixes, char **ext1_suffixes,
173 char **ext2_suffixes, char **ext3_suffixes,
174 char **ignore_tokens)
178 image_info = checked_calloc(sizeof(struct ArtworkListInfo));
179 image_info->type = ARTWORK_TYPE_GRAPHICS;
181 // ---------- initialize file list and suffix lists ----------
183 image_info->num_file_list_entries = num_file_list_entries;
184 image_info->num_dynamic_file_list_entries = 0;
186 image_info->file_list =
187 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
188 num_file_list_entries);
189 image_info->dynamic_file_list = NULL;
191 image_info->num_suffix_list_entries = 0;
192 for (i = 0; config_suffix_list[i].token != NULL; i++)
193 image_info->num_suffix_list_entries++;
195 image_info->suffix_list = config_suffix_list;
197 // ---------- initialize base prefix and suffixes lists ----------
199 image_info->num_base_prefixes = 0;
200 for (i = 0; base_prefixes[i] != NULL; i++)
201 image_info->num_base_prefixes++;
203 image_info->num_ext1_suffixes = 0;
204 for (i = 0; ext1_suffixes[i] != NULL; i++)
205 image_info->num_ext1_suffixes++;
207 image_info->num_ext2_suffixes = 0;
208 for (i = 0; ext2_suffixes[i] != NULL; i++)
209 image_info->num_ext2_suffixes++;
211 image_info->num_ext3_suffixes = 0;
212 for (i = 0; ext3_suffixes[i] != NULL; i++)
213 image_info->num_ext3_suffixes++;
215 image_info->num_ignore_tokens = 0;
216 for (i = 0; ignore_tokens[i] != NULL; i++)
217 image_info->num_ignore_tokens++;
219 image_info->base_prefixes = base_prefixes;
220 image_info->ext1_suffixes = ext1_suffixes;
221 image_info->ext2_suffixes = ext2_suffixes;
222 image_info->ext3_suffixes = ext3_suffixes;
223 image_info->ignore_tokens = ignore_tokens;
225 image_info->num_property_mapping_entries = 0;
227 image_info->property_mapping = NULL;
229 // ---------- initialize artwork reference and content lists ----------
231 image_info->sizeof_artwork_list_entry = sizeof(ImageInfo *);
233 image_info->artwork_list =
234 checked_calloc(num_file_list_entries * sizeof(ImageInfo *));
235 image_info->dynamic_artwork_list = NULL;
237 image_info->content_list = NULL;
239 // ---------- initialize artwork loading/freeing functions ----------
241 image_info->load_artwork = Load_Image;
242 image_info->free_artwork = FreeImage;
245 void ReloadCustomImages(void)
247 print_timestamp_init("ReloadCustomImages");
249 LoadArtworkConfig(image_info);
250 print_timestamp_time("LoadArtworkConfig");
252 ReloadCustomArtworkList(image_info);
253 print_timestamp_time("ReloadCustomArtworkList");
255 print_timestamp_done("ReloadCustomImages");
258 static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
261 if (!img_info->contains_small_images)
264 // at this point, small images already exist for this image;
265 // now do some checks that may require re-creating small (or in-game) images
269 // check if the configured tile size for an already loaded image has changed
270 // from one level set to another; this should usually not happen, but if a
271 // custom artwork set redefines classic (or default) graphics with wrong tile
272 // size (by mistake or by intention), it will be corrected to its original
273 // tile size here by forcing complete re-creation of all small images again
275 if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
276 img_info->conf_tile_size != tile_size)
278 int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
281 // free all calculated, resized bitmaps, but keep last configured size
282 for (i = 0; i < NUM_IMG_BITMAPS; i++)
287 if (img_info->bitmaps[i])
289 FreeBitmap(img_info->bitmaps[i]);
291 img_info->bitmaps[i] = NULL;
295 // re-create small bitmaps from last configured size as new default size
296 if (bitmap_nr != IMG_BITMAP_STANDARD)
298 img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
299 img_info->bitmaps[bitmap_nr] = NULL;
302 img_info->contains_small_images = FALSE;
307 // special case 1 (continued):
309 // if different tile sizes are used in same image file (usually by mistake,
310 // like forgetting option ".tile_size" for one or more graphic definitions),
311 // make sure to use only the first tile size that is processed for this image
312 // (and ignore all subsequent, potentially different tile size definitions
313 // for this image within the current level set by disabling the above check)
315 setString(&img_info->leveldir, leveldir_current->identifier);
319 // graphic config setting "game.tile_size" has changed since last level set;
320 // this may require resizing image to new size required for in-game graphics
322 if (img_info->game_tile_size != gfx.game_tile_size)
324 ReCreateGameTileSizeBitmap(img_info->bitmaps);
326 img_info->game_tile_size = gfx.game_tile_size;
332 void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
334 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
336 if (img_info == NULL)
339 if (CheckIfImageContainsSmallImages(img_info, tile_size))
342 CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
344 img_info->contains_small_images = TRUE;
345 img_info->scaled_up = TRUE; // scaling was also done here
347 img_info->conf_tile_size = tile_size;
348 img_info->game_tile_size = gfx.game_tile_size;
350 setString(&img_info->leveldir, leveldir_current->identifier);
353 void CreateImageTextures(int pos)
355 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
357 if (img_info == NULL || img_info->contains_textures)
360 CreateBitmapTextures(img_info->bitmaps);
362 img_info->contains_textures = TRUE;
365 static void FreeImageTextures(int pos)
367 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
369 if (img_info == NULL || !img_info->contains_textures)
372 FreeBitmapTextures(img_info->bitmaps);
374 img_info->contains_textures = FALSE;
377 void FreeAllImageTextures(void)
379 int num_images = getImageListSize();
382 for (i = 0; i < num_images; i++)
383 FreeImageTextures(i);
386 void ScaleImage(int pos, int zoom_factor)
388 ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
390 if (img_info == NULL || img_info->scaled_up)
393 if (zoom_factor != 1)
395 ScaleBitmap(img_info->bitmaps, zoom_factor);
397 img_info->scaled_up = TRUE;
401 void FreeAllImages(void)
403 FreeCustomArtworkLists(image_info);