re-enabled storing selection from "last played level set" menu
[rocksndiamonds.git] / src / tools.c
index 2157ef740c812d23b87ba6cb453781c2eec7b877..b0df34409cfbc97772af22c78e8815c9ae6c3644 100644 (file)
@@ -391,6 +391,16 @@ int getLevelFromScreenY(int y)
     return getLevelFromScreenY_RND(y);
 }
 
+int getScreenFieldSizeX(void)
+{
+  return (tape.playing ? tape.scr_fieldx : SCR_FIELDX);
+}
+
+int getScreenFieldSizeY(void)
+{
+  return (tape.playing ? tape.scr_fieldy : SCR_FIELDY);
+}
+
 void DumpTile(int x, int y)
 {
   int sx = SCREENX(x);
@@ -1950,6 +1960,9 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
       graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
       frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
     }
+
+    if (game.use_masked_elements && (dx || dy))
+      mask_mode = USE_MASKING;
   }
   else // border element
   {
@@ -2068,8 +2081,27 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
   cx = (dx > 0 ? TILESIZE_VAR - width  : 0);
   cy = (dy > 0 ? TILESIZE_VAR - height : 0);
 
-  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
-            width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+  if (game.use_masked_elements)
+  {
+    int graphic0 = el2img(EL_EMPTY);
+    int frame0 = getGraphicAnimationFrame(graphic0, GfxFrame[x][y]);
+    Bitmap *src_bitmap0;
+    int src_x0, src_y0;
+
+    getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
+    BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+
+    BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                    width, height,
+                    FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+  }
+  else
+    BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
 }
 
 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
@@ -2088,6 +2120,15 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
 
   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
 
+  // only needed when using masked elements
+  int graphic0 = el2img(EL_EMPTY);
+  int frame0 = getGraphicAnimationFrame(graphic0, GfxFrame[x][y]);
+  Bitmap *src_bitmap0;
+  int src_x0, src_y0;
+
+  if (game.use_masked_elements)
+    getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
   // draw simple, sloppy, non-corner-accurate crumbled border
 
   width  = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
@@ -2095,9 +2136,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
   cx = (dir == 2 ? crumbled_border_pos_var : 0);
   cy = (dir == 3 ? crumbled_border_pos_var : 0);
 
-  BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, width, height,
-            FX + sx * TILEX_VAR + cx,
-            FY + sy * TILEY_VAR + cy);
+  if (game.use_masked_elements)
+  {
+    BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx,
+              FY + sy * TILEY_VAR + cy);
+
+    BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+                    width, height,
+                    FX + sx * TILEX_VAR + cx,
+                    FY + sy * TILEY_VAR + cy);
+  }
+  else
+    BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+              width, height,
+              FX + sx * TILEX_VAR + cx,
+              FY + sy * TILEY_VAR + cy);
 
   // (remaining middle border part must be at least as big as corner part)
   if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
@@ -2143,10 +2198,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
        by = cy;
       }
 
-      BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
-                width, height,
-                FX + sx * TILEX_VAR + cx,
-                FY + sy * TILEY_VAR + cy);
+      if (game.use_masked_elements)
+      {
+       BlitBitmap(src_bitmap0, drawto_field, src_x0 + bx, src_y0 + by,
+                  width, height,
+                  FX + sx * TILEX_VAR + cx,
+                  FY + sy * TILEY_VAR + cy);
+
+       BlitBitmapMasked(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                        width, height,
+                        FX + sx * TILEX_VAR + cx,
+                        FY + sy * TILEY_VAR + cy);
+      }
+      else
+       BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+                  width, height,
+                  FX + sx * TILEX_VAR + cx,
+                  FY + sy * TILEY_VAR + cy);
     }
   }
 }
@@ -2301,7 +2369,7 @@ void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
   int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
   int sx = SCREENX(x), sy = SCREENY(y);
 
-  DrawGraphic(sx, sy, graphic1, frame1);
+  DrawScreenGraphic(sx, sy, graphic1, frame1);
   DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
 }
 
@@ -2382,9 +2450,38 @@ static int getBorderElement(int x, int y)
   return border[steel_position][steel_type];
 }
 
+void DrawScreenGraphic(int x, int y, int graphic, int frame)
+{
+  if (game.use_masked_elements)
+  {
+    if (graphic != el2img(EL_EMPTY))
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+    DrawGraphicThruMask(x, y, graphic, frame);
+  }
+  else
+  {
+    DrawGraphic(x, y, graphic, frame);
+  }
+}
+
 void DrawScreenElement(int x, int y, int element)
 {
-  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+  int mask_mode = NO_MASKING;
+
+  if (game.use_masked_elements)
+  {
+    int lx = LEVELX(x), ly = LEVELY(y);
+
+    if (IN_LEV_FIELD(lx, ly) && element != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
+  DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, mask_mode);
   DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
 }
 
@@ -2810,6 +2907,53 @@ void ShowEnvelope(int envelope_nr)
   BackToFront();
 }
 
+static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
+                                          int xsize, int ysize)
+{
+  if (!global.use_envelope_request ||
+      request.sort_priority <= 0)
+    return;
+
+  if (request.bitmap == NULL ||
+      xsize > request.xsize ||
+      ysize > request.ysize)
+  {
+    if (request.bitmap != NULL)
+      FreeBitmap(request.bitmap);
+
+    request.bitmap = CreateBitmap(xsize, ysize, DEFAULT_DEPTH);
+
+    SDL_Surface *surface = request.bitmap->surface;
+
+    if ((request.bitmap->surface_masked = SDLGetNativeSurface(surface)) == NULL)
+      Fail("SDLGetNativeSurface() failed");
+  }
+
+  BlitBitmap(bitmap, request.bitmap, sx, sy, xsize, ysize, 0, 0);
+
+  SDLFreeBitmapTextures(request.bitmap);
+  SDLCreateBitmapTextures(request.bitmap);
+
+  // set envelope request run-time values
+  request.sx = sx;
+  request.sy = sy;
+  request.xsize = xsize;
+  request.ysize = ysize;
+}
+
+void DrawEnvelopeRequestToScreen(int drawing_target, int drawing_stage)
+{
+  if (global.use_envelope_request &&
+      game.request_active_or_moving &&
+      request.sort_priority > 0 &&
+      drawing_target == DRAW_TO_SCREEN &&
+      drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2)
+  {
+    BlitToScreen(request.bitmap, 0, 0, request.xsize, request.ysize,
+                request.sx, request.sy);
+  }
+}
+
 static void setRequestBasePosition(int *x, int *y)
 {
   int sx_base, sy_base;
@@ -2960,6 +3104,8 @@ static void DrawEnvelopeRequest(char *text)
   // store readily prepared envelope request for later use when animating
   BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
 
+  PrepareEnvelopeRequestToScreen(bitmap_db_store_2, sx, sy, width, height);
+
   if (text_door_style)
     free(text_door_style);
 }
@@ -3041,6 +3187,8 @@ static void AnimateEnvelopeRequest(int anim_mode, int action)
       }
     }
 
+    PrepareEnvelopeRequestToScreen(backbuffer, dst_x, dst_y, width, height);
+
     redraw_mask |= REDRAW_FIELD;
 
     BackToFront();
@@ -3686,12 +3834,23 @@ void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
 static void DrawGraphicAnimation(int x, int y, int graphic)
 {
   int lx = LEVELX(x), ly = LEVELY(y);
+  int mask_mode = NO_MASKING;
 
   if (!IN_SCR_FIELD(x, y))
     return;
 
+  if (game.use_masked_elements)
+  {
+    if (Tile[lx][ly] != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
-                         graphic, GfxFrame[lx][ly], NO_MASKING);
+                         graphic, GfxFrame[lx][ly], mask_mode);
 
   MarkTileDirty(x, y);
 }
@@ -3699,12 +3858,24 @@ static void DrawGraphicAnimation(int x, int y, int graphic)
 void DrawFixedGraphicAnimation(int x, int y, int graphic)
 {
   int lx = LEVELX(x), ly = LEVELY(y);
+  int mask_mode = NO_MASKING;
 
   if (!IN_SCR_FIELD(x, y))
     return;
 
+  if (game.use_masked_elements)
+  {
+    if (Tile[lx][ly] != EL_EMPTY)
+    {
+      DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+      mask_mode = USE_MASKING;
+    }
+  }
+
   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
-                         graphic, GfxFrame[lx][ly], NO_MASKING);
+                         graphic, GfxFrame[lx][ly], mask_mode);
+
   MarkTileDirty(x, y);
 }
 
@@ -3963,7 +4134,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
       if (GFX_CRUMBLED(old_element))
        DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
       else
-       DrawGraphic(sx, sy, old_graphic, frame);
+       DrawScreenGraphic(sx, sy, old_graphic, frame);
 
       if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
        static_player_is_opaque[pnr] = TRUE;
@@ -4213,7 +4384,7 @@ void WaitForEventToContinue(void)
 #define MAX_REQUEST_LINE_FONT1_LEN     7
 #define MAX_REQUEST_LINE_FONT2_LEN     10
 
-static int RequestHandleEvents(unsigned int req_state)
+static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game)
 {
   boolean game_just_ended = (game_status == GAME_MODE_PLAYING &&
                             checkGameEnded());
@@ -4238,9 +4409,11 @@ static int RequestHandleEvents(unsigned int req_state)
 
   while (result < 0)
   {
+    boolean event_handled = FALSE;
+
     if (game_just_ended)
     {
-      SetDrawtoField(draw_buffer_last);
+      SetDrawtoField(draw_buffer_game);
 
       HandleGameActions();
 
@@ -4259,6 +4432,8 @@ static int RequestHandleEvents(unsigned int req_state)
 
       while (NextValidEvent(&event))
       {
+       event_handled = TRUE;
+
        switch (event.type)
        {
          case EVENT_BUTTONPRESS:
@@ -4513,13 +4688,18 @@ static int RequestHandleEvents(unsigned int req_state)
       }
     }
 
-    if (game_just_ended)
+    if (event_handled)
     {
-      if (global.use_envelope_request)
+      if (game_just_ended)
       {
-       // copy back current state of pressed buttons inside request area
-       BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+       if (global.use_envelope_request)
+       {
+         // copy back current state of pressed buttons inside request area
+         BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+       }
       }
+
+      PrepareEnvelopeRequestToScreen(drawto, sx, sy, width, height);
     }
 
     BackToFront();
@@ -4534,6 +4714,7 @@ static int RequestHandleEvents(unsigned int req_state)
 
 static boolean RequestDoor(char *text, unsigned int req_state)
 {
+  int draw_buffer_last = GetDrawtoField();
   unsigned int old_door_state;
   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
   int font_nr = FONT_TEXT_2;
@@ -4675,7 +4856,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
   // ---------- handle request buttons ----------
-  result = RequestHandleEvents(req_state);
+  result = RequestHandleEvents(req_state, draw_buffer_last);
 
   UnmapToolButtons();
 
@@ -4716,6 +4897,7 @@ static boolean RequestDoor(char *text, unsigned int req_state)
 
 static boolean RequestEnvelope(char *text, unsigned int req_state)
 {
+  int draw_buffer_last = GetDrawtoField();
   int result;
 
   if (game_status == GAME_MODE_PLAYING)
@@ -4767,7 +4949,7 @@ static boolean RequestEnvelope(char *text, unsigned int req_state)
   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
 
   // ---------- handle request buttons ----------
-  result = RequestHandleEvents(req_state);
+  result = RequestHandleEvents(req_state, draw_buffer_last);
 
   UnmapToolButtons();
 
@@ -4804,6 +4986,8 @@ boolean Request(char *text, unsigned int req_state)
   boolean overlay_enabled = GetOverlayEnabled();
   boolean result;
 
+  game.request_active_or_moving = TRUE;
+
   SetOverlayEnabled(FALSE);
 
   if (global.use_envelope_request)
@@ -4813,6 +4997,8 @@ boolean Request(char *text, unsigned int req_state)
 
   SetOverlayEnabled(overlay_enabled);
 
+  game.request_active_or_moving = FALSE;
+
   return result;
 }