fixed graphic problems caused by bugs in custom graphics of previous level set
authorHolger Schemel <info@artsoft.org>
Thu, 13 Aug 2015 10:45:51 +0000 (12:45 +0200)
committerHolger Schemel <info@artsoft.org>
Thu, 13 Aug 2015 10:45:51 +0000 (12:45 +0200)
src/libgame/image.c
src/libgame/image.h

index 799b28bb926cd2e07960aba5a744a6c36e1b3195..14fd7c65de90badadcab8c8d79e3baec070831e0 100644 (file)
@@ -27,7 +27,10 @@ struct ImageInfo
   boolean contains_small_images;       /* set after adding small images */
   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;
 
@@ -55,8 +58,11 @@ static void *Load_Image(char *filename)
   img_info->contains_small_images = 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;
 }
 
@@ -248,29 +254,101 @@ 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
+  // (this does not work if different tile sizes are used in same image file)
+
+  if (!strEqual(img_info->leveldir, leveldir_current->identifier) &&
+      img_info->conf_tile_size != tile_size)
+  {
+#if 0
+    printf("::: RE-CREATING DEFAULT TILE SIZE: %d -> %d\n",
+          img_info->conf_tile_size, tile_size);
+#endif
+
+    int bitmap_nr = GET_BITMAP_ID_FROM_TILESIZE(img_info->conf_tile_size);
+    int i;
+
+    // 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;
+      }
+    }
+
+    // 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;
+  }
 
-  if (img_info == NULL)
-    return;
+  // 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->contains_small_images)
+  if (img_info->game_tile_size != gfx.game_tile_size)
   {
-    if (img_info->game_tile_size != gfx.game_tile_size)
-      ReCreateGameTileSizeBitmap(img_info->bitmaps);
+#if 0
+    if (strSuffix(img_info->source_filename, "RocksHeroes.png"))
+      printf("::: RE-CREATING IN-GAME TILE SIZE: %d -> %d\n",
+            img_info->game_tile_size, gfx.game_tile_size);
+#endif
+
+    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 ScaleImage(int pos, int zoom_factor)
index adcc9e65dff01f53faa6110e36dc146657cb8863..db988c6bf0012891fc3658c7652a957f9f2d877d 100644 (file)
 #define IMG_BITMAP_STANDARD    IMG_BITMAP_32x32
 
 
+#define GET_BITMAP_ID_FROM_TILESIZE(x) ((x) ==  1 ? IMG_BITMAP_1x1   : \
+                                        (x) ==  2 ? IMG_BITMAP_2x2   : \
+                                        (x) ==  4 ? IMG_BITMAP_4x4   : \
+                                        (x) ==  8 ? IMG_BITMAP_8x8   : \
+                                        (x) == 16 ? IMG_BITMAP_16x16 : \
+                                        (x) == 32 ? IMG_BITMAP_32x32 : \
+                                        IMG_BITMAP_CUSTOM)
+
+#define GET_TILESIZE_FROM_BITMAP_ID(x) ((x) == IMG_BITMAP_1x1   ? 1  : \
+                                        (x) == IMG_BITMAP_2x2   ? 2  : \
+                                        (x) == IMG_BITMAP_4x4   ? 4  : \
+                                        (x) == IMG_BITMAP_8x8   ? 8  : \
+                                        (x) == IMG_BITMAP_16x16 ? 16 : \
+                                        (x) == IMG_BITMAP_32x32 ? 32 : \
+                                        0)
+
+
 int getImageListSize();
 struct FileInfo *getImageListEntryFromImageID(int);
 Bitmap **getBitmapsFromImageID(int);