rnd-20060805-2-src
[rocksndiamonds.git] / src / tools.c
index 3a2b962a3469435f1d8f00d6acf497f5be894d87..f7a3011e0e1b4a71882de655a283fa444bf46e41 100644 (file)
@@ -44,6 +44,8 @@ static int el_act2crm(int, int);
 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
 static int request_gadget_id = -1;
 
+static int preview_tilesize = TILEX / 4;
+
 static char *print_if_not_empty(int element)
 {
   static char *s = NULL;
@@ -1493,6 +1495,37 @@ void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
   *y = src_y;
 }
 
+void getPreviewGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y,
+                            int tilesize)
+{
+  struct
+  {
+    int width_mult, width_div;
+    int height_mult, height_div;
+  } offset_calc[4] =
+  {
+    { 0, 1,    0, 1    },
+    { 0, 1,    2, 3    },
+    { 1, 2,    2, 3    },
+    { 3, 4,    2, 3    },
+  };
+  int offset_calc_pos = (tilesize < MICRO_TILESIZE || tilesize > TILESIZE ? 3 :
+                        5 - log_2(tilesize));
+  Bitmap *src_bitmap = graphic_info[graphic].bitmap;
+  int width_mult = offset_calc[offset_calc_pos].width_mult;
+  int width_div = offset_calc[offset_calc_pos].width_div;
+  int height_mult = offset_calc[offset_calc_pos].height_mult;
+  int height_div = offset_calc[offset_calc_pos].height_div;
+  int mini_startx = src_bitmap->width * width_mult / width_div;
+  int mini_starty = src_bitmap->height * height_mult / height_div;
+  int src_x = mini_startx + graphic_info[graphic].src_x * tilesize / TILESIZE;
+  int src_y = mini_starty + graphic_info[graphic].src_y * tilesize / TILESIZE;
+
+  *bitmap = src_bitmap;
+  *x = src_x;
+  *y = src_y;
+}
+
 void DrawMicroElement(int xpos, int ypos, int element)
 {
   Bitmap *src_bitmap;
@@ -1504,6 +1537,16 @@ void DrawMicroElement(int xpos, int ypos, int element)
             xpos, ypos);
 }
 
+void DrawPreviewElement(int xpos, int ypos, int element, int tilesize)
+{
+  Bitmap *src_bitmap;
+  int src_x, src_y;
+  int graphic = el2preimg(element);
+
+  getPreviewGraphicSource(graphic, &src_bitmap, &src_x, &src_y, tilesize);
+  BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, xpos, ypos);
+}
+
 void DrawLevel()
 {
   int x,y;
@@ -1531,31 +1574,32 @@ void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
 
 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
 {
+  boolean show_level_border = (BorderElement != EL_EMPTY);
+  int level_size_x = lev_fieldx + (show_level_border ? 2 : 0);
+  int level_size_y = lev_fieldy + (show_level_border ? 2 : 0);
+  int preview_size_x = MICROLEVEL_XSIZE / preview_tilesize;
+  int preview_size_y = MICROLEVEL_YSIZE / preview_tilesize;
+  int real_preview_size_x = MIN(level_size_x, preview_size_x);
+  int real_preview_size_y = MIN(level_size_y, preview_size_y);
   int x, y;
 
   DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE);
 
-  if (lev_fieldx < STD_LEV_FIELDX)
-    xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
-  if (lev_fieldy < STD_LEV_FIELDY)
-    ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
+  xpos += (MICROLEVEL_XSIZE - real_preview_size_x * preview_tilesize) / 2;
+  ypos += (MICROLEVEL_YSIZE - real_preview_size_y * preview_tilesize) / 2;
 
-  xpos += MICRO_TILEX;
-  ypos += MICRO_TILEY;
-
-  for (x = -1; x <= STD_LEV_FIELDX; x++)
+  for (x = 0; x < real_preview_size_x; x++)
   {
-    for (y = -1; y <= STD_LEV_FIELDY; y++)
+    for (y = 0; y < real_preview_size_y; y++)
     {
-      int lx = from_x + x, ly = from_y + y;
-
-      if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
-       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        level.field[lx][ly]);
-      else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
-              && BorderElement != EL_EMPTY)
-       DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
-                        getBorderElement(lx, ly));
+      int lx = from_x + x + (show_level_border ? -1 : 0);
+      int ly = from_y + y + (show_level_border ? -1 : 0);
+      int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
+                    getBorderElement(lx, ly));
+
+      DrawPreviewElement(xpos + x * preview_tilesize,
+                        ypos + y * preview_tilesize,
+                        element, preview_tilesize);
     }
   }
 
@@ -1625,6 +1669,13 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart)
   static unsigned long label_delay = 0;
   static int from_x, from_y, scroll_direction;
   static int label_state, label_counter;
+  int delay_factor = preview_tilesize / MICRO_TILESIZE;
+  unsigned long scroll_delay_value = MICROLEVEL_SCROLL_DELAY * delay_factor;
+  boolean show_level_border = (BorderElement != EL_EMPTY);
+  int level_size_x = lev_fieldx + (show_level_border ? 2 : 0);
+  int level_size_y = lev_fieldy + (show_level_border ? 2 : 0);
+  int preview_size_x = MICROLEVEL_XSIZE / preview_tilesize;
+  int preview_size_y = MICROLEVEL_YSIZE / preview_tilesize;
   int last_game_status = game_status;  /* save current game status */
 
   /* force PREVIEW font on preview level */
@@ -1666,8 +1717,8 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart)
   }
 
   /* scroll micro level, if needed */
-  if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
-      DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
+  if ((level_size_x > preview_size_x || level_size_y > preview_size_y) &&
+      DelayReached(&scroll_delay, scroll_delay_value))
   {
     switch (scroll_direction)
     {
@@ -1679,7 +1730,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart)
        break;
 
       case MV_RIGHT:
-       if (from_x < lev_fieldx - STD_LEV_FIELDX)
+       if (from_x < level_size_x - preview_size_x)
          from_x++;
        else
          scroll_direction = MV_DOWN;
@@ -1693,7 +1744,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart)
        break;
 
       case MV_DOWN:
-       if (from_y < lev_fieldy - STD_LEV_FIELDY)
+       if (from_y < level_size_y - preview_size_y)
          from_y++;
        else
          scroll_direction = MV_LEFT;
@@ -5986,3 +6037,33 @@ void PlayMenuMusic()
 
   PlayMusic(music);
 }
+
+void ToggleFullscreenIfNeeded()
+{
+  if (setup.fullscreen != video.fullscreen_enabled ||
+      setup.fullscreen_mode != video.fullscreen_mode_current)
+  {
+    Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+
+    /* save backbuffer content which gets lost when toggling fullscreen mode */
+    BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+    if (setup.fullscreen && video.fullscreen_enabled)
+    {
+      /* keep fullscreen mode, but change screen mode */
+      video.fullscreen_mode_current = setup.fullscreen_mode;
+      video.fullscreen_enabled = FALSE;
+    }
+
+    /* toggle fullscreen */
+    ChangeVideoModeIfNeeded(setup.fullscreen);
+    setup.fullscreen = video.fullscreen_enabled;
+
+    /* restore backbuffer content from temporary backbuffer backup bitmap */
+    BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+    FreeBitmap(tmp_backbuffer);
+
+    redraw_mask = REDRAW_ALL;
+  }
+}