added support for special media buttons on Amazon Fire TV remote control
[rocksndiamonds.git] / src / libgame / image.c
index 799b28bb926cd2e07960aba5a744a6c36e1b3195..699093b7b7ebb718e6a6d74144ba3c5b81caada8 100644 (file)
@@ -25,9 +25,13 @@ struct ImageInfo
   int original_height;                 /* original image file height */
 
   boolean contains_small_images;       /* set after adding small images */
+  boolean contains_textures;           /* set after adding GPU textures */
   boolean scaled_up;                   /* set after scaling up */
 
-  int game_tile_size;                  /* size of in-game sized bitmap */
+  int conf_tile_size;                  /* tile size as defined in config */
+  int game_tile_size;                  /* tile size as resized for game */
+
+  char *leveldir;                      /* level set when image was loaded */
 };
 typedef struct ImageInfo ImageInfo;
 
@@ -53,10 +57,14 @@ static void *Load_Image(char *filename)
   img_info->original_height = img_info->bitmaps[IMG_BITMAP_STANDARD]->height;
 
   img_info->contains_small_images = FALSE;
+  img_info->contains_textures = FALSE;
   img_info->scaled_up = FALSE;
 
+  img_info->conf_tile_size = 0;                // will be set later
   img_info->game_tile_size = 0;                // will be set later
 
+  img_info->leveldir = NULL;           // will be set later
+
   return img_info;
 }
 
@@ -132,6 +140,13 @@ char *getTokenFromImageID(int graphic)
   return (file_list != NULL ? file_list->token : NULL);
 }
 
+char *getFilenameFromImageID(int graphic)
+{
+  struct FileInfo *file_list = getImageListEntryFromImageID(graphic);
+
+  return (file_list != NULL ? file_list->filename : NULL);
+}
+
 int getImageIDFromToken(char *token)
 {
   struct FileInfo *file_list = image_info->file_list;
@@ -248,29 +263,132 @@ void ReloadCustomImages()
   print_timestamp_done("ReloadCustomImages");
 }
 
-void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
+static boolean CheckIfImageContainsSmallImages(ImageInfo *img_info,
+                                              int tile_size)
 {
-  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+  if (!img_info->contains_small_images)
+    return FALSE;
+
+  // at this point, small images already exist for this image;
+  // now do some checks that may require re-creating small (or in-game) images
+
+  // special case 1:
+  //
+  // check if the configured tile size for an already loaded image has changed
+  // from one level set to another; this should usually not happen, but if a
+  // custom artwork set redefines classic (or default) graphics with wrong tile
+  // size (by mistake or by intention), it will be corrected to its original
+  // tile size here by forcing complete re-creation of all small images again
+
+  if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
+      img_info->conf_tile_size != tile_size)
+  {
+    int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
+    int i;
 
-  if (img_info == NULL)
-    return;
+    // free all calculated, resized bitmaps, but keep last configured size
+    for (i = 0; i < NUM_IMG_BITMAPS; i++)
+    {
+      if (i == bitmap_nr)
+       continue;
+
+      if (img_info->bitmaps[i])
+      {
+       FreeBitmap(img_info->bitmaps[i]);
+
+       img_info->bitmaps[i] = NULL;
+      }
+    }
 
-  if (img_info->contains_small_images)
+    // re-create small bitmaps from last configured size as new default size
+    if (bitmap_nr != IMG_BITMAP_STANDARD)
+    {
+      img_info->bitmaps[IMG_BITMAP_STANDARD] = img_info->bitmaps[bitmap_nr];
+      img_info->bitmaps[bitmap_nr] = NULL;
+    }
+
+    img_info->contains_small_images = FALSE;
+
+    return FALSE;
+  }
+
+  // special case 1 (continued):
+  //
+  // if different tile sizes are used in same image file (usually by mistake,
+  // like forgetting option ".tile_size" for one or more graphic definitions),
+  // make sure to use only the first tile size that is processed for this image
+  // (and ignore all subsequent, potentially different tile size definitions
+  // for this image within the current level set by disabling the above check)
+
+  setString(&img_info->leveldir, leveldir_current->identifier);
+
+  // special case 2:
+  //
+  // graphic config setting "game.tile_size" has changed since last level set;
+  // this may require resizing image to new size required for in-game graphics
+
+  if (img_info->game_tile_size != gfx.game_tile_size)
   {
-    if (img_info->game_tile_size != gfx.game_tile_size)
-      ReCreateGameTileSizeBitmap(img_info->bitmaps);
+    ReCreateGameTileSizeBitmap(img_info->bitmaps);
 
     img_info->game_tile_size = gfx.game_tile_size;
+  }
+
+  return TRUE;
+}
+
+void CreateImageWithSmallImages(int pos, int zoom_factor, int tile_size)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
 
+  if (img_info == NULL)
+    return;
+
+  if (CheckIfImageContainsSmallImages(img_info, tile_size))
     return;
-  }
 
   CreateBitmapWithSmallBitmaps(img_info->bitmaps, zoom_factor, tile_size);
 
   img_info->contains_small_images = TRUE;
   img_info->scaled_up = TRUE;                  // scaling was also done here
 
+  img_info->conf_tile_size = tile_size;
   img_info->game_tile_size = gfx.game_tile_size;
+
+  setString(&img_info->leveldir, leveldir_current->identifier);
+}
+
+void CreateImageTextures(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  if (img_info == NULL || img_info->contains_textures)
+    return;
+
+  CreateBitmapTextures(img_info->bitmaps);
+
+  img_info->contains_textures = TRUE;
+}
+
+void FreeImageTextures(int pos)
+{
+  ImageInfo *img_info = getImageInfoEntryFromImageID(pos);
+
+  if (img_info == NULL || !img_info->contains_textures)
+    return;
+
+  FreeBitmapTextures(img_info->bitmaps);
+
+  img_info->contains_textures = FALSE;
+}
+
+void FreeAllImageTextures()
+{
+  int num_images = getImageListSize();
+  int i;
+
+  for (i = 0; i < num_images; i++)
+    FreeImageTextures(i);
 }
 
 void ScaleImage(int pos, int zoom_factor)