cleanup of state changes before/after fading in/out (more generic approach)
[rocksndiamonds.git] / src / tools.c
index 4a5243602014051440e8ae14fca474bce98b5c9e..cff76238c3b2f2c6db6fd6e6460aa885010e6951 100644 (file)
@@ -24,7 +24,8 @@
 
 
 /* select level set with EMC X11 graphics before activating EM GFX debugging */
-#define DEBUG_EM_GFX   0
+#define DEBUG_EM_GFX           FALSE
+#define DEBUG_FRAME_TIME       FALSE
 
 /* tool button identifiers */
 #define TOOL_CTRL_ID_YES       0
@@ -288,62 +289,67 @@ void RedrawPlayfield()
 }
 
 static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height,
-                                    boolean blit_to_screen)
+                                    int draw_target)
 {
   Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
 
-  if (blit_to_screen)
+  if (x == -1 && y == -1)
+    return;
+
+  if (draw_target == DRAW_BORDER_TO_SCREEN)
     BlitToScreenMasked(bitmap, x, y, width, height, x, y);
   else
     BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
 }
 
-static void DrawMaskedBorderExt_FIELD(boolean blit_to_screen)
+static void DrawMaskedBorderExt_FIELD(int draw_target)
 {
   if (global.border_status >= GAME_MODE_TITLE &&
       global.border_status <= GAME_MODE_PLAYING &&
       border.draw_masked[global.border_status])
     DrawMaskedBorderExt_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
-                            blit_to_screen);
+                            draw_target);
 }
 
-static void DrawMaskedBorderExt_DOOR_1(boolean blit_to_screen)
+static void DrawMaskedBorderExt_DOOR_1(int draw_target)
 {
-  // only draw border over closed doors when drawing to backbuffer
-  if (!blit_to_screen && (GetDoorState() & DOOR_OPEN_1))
+  // when drawing to backbuffer, never draw border over open doors
+  if (draw_target == DRAW_BORDER_TO_BACKBUFFER &&
+      (GetDoorState() & DOOR_OPEN_1))
     return;
 
   if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
       (global.border_status != GAME_MODE_EDITOR ||
        border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
-    DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, blit_to_screen);
+    DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, draw_target);
 }
 
-static void DrawMaskedBorderExt_DOOR_2(boolean blit_to_screen)
+static void DrawMaskedBorderExt_DOOR_2(int draw_target)
 {
-  // only draw border over closed doors when drawing to backbuffer
-  if (!blit_to_screen && (GetDoorState() & DOOR_OPEN_2))
+  // when drawing to backbuffer, never draw border over open doors
+  if (draw_target == DRAW_BORDER_TO_BACKBUFFER &&
+      (GetDoorState() & DOOR_OPEN_2))
     return;
 
   if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
       global.border_status != GAME_MODE_EDITOR)
-    DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, blit_to_screen);
+    DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, draw_target);
 }
 
-static void DrawMaskedBorderExt_DOOR_3(boolean blit_to_screen)
+static void DrawMaskedBorderExt_DOOR_3(int draw_target)
 {
   /* currently not available */
 }
 
-static void DrawMaskedBorderExt_ALL(boolean blit_to_screen)
+static void DrawMaskedBorderExt_ALL(int draw_target)
 {
-  DrawMaskedBorderExt_FIELD(blit_to_screen);
-  DrawMaskedBorderExt_DOOR_1(blit_to_screen);
-  DrawMaskedBorderExt_DOOR_2(blit_to_screen);
-  DrawMaskedBorderExt_DOOR_3(blit_to_screen);
+  DrawMaskedBorderExt_FIELD(draw_target);
+  DrawMaskedBorderExt_DOOR_1(draw_target);
+  DrawMaskedBorderExt_DOOR_2(draw_target);
+  DrawMaskedBorderExt_DOOR_3(draw_target);
 }
 
-static void DrawMaskedBorderExt(int redraw_mask, boolean blit_to_screen)
+static void DrawMaskedBorderExt(int redraw_mask, int draw_target)
 {
   /* never draw masked screen borders on borderless screens */
   if (game_status == GAME_MODE_LOADING ||
@@ -351,33 +357,33 @@ static void DrawMaskedBorderExt(int redraw_mask, boolean blit_to_screen)
     return;
 
   if (redraw_mask & REDRAW_ALL)
-    DrawMaskedBorderExt_ALL(blit_to_screen);
+    DrawMaskedBorderExt_ALL(draw_target);
   else
   {
     if (redraw_mask & REDRAW_FIELD)
-      DrawMaskedBorderExt_FIELD(blit_to_screen);
+      DrawMaskedBorderExt_FIELD(draw_target);
     if (redraw_mask & REDRAW_DOOR_1)
-      DrawMaskedBorderExt_DOOR_1(blit_to_screen);
+      DrawMaskedBorderExt_DOOR_1(draw_target);
     if (redraw_mask & REDRAW_DOOR_2)
-      DrawMaskedBorderExt_DOOR_2(blit_to_screen);
+      DrawMaskedBorderExt_DOOR_2(draw_target);
     if (redraw_mask & REDRAW_DOOR_3)
-      DrawMaskedBorderExt_DOOR_3(blit_to_screen);
+      DrawMaskedBorderExt_DOOR_3(draw_target);
   }
 }
 
 void DrawMaskedBorder_FIELD()
 {
-  DrawMaskedBorderExt_FIELD(FALSE);
+  DrawMaskedBorderExt_FIELD(DRAW_BORDER_TO_BACKBUFFER);
 }
 
 void DrawMaskedBorder(int redraw_mask)
 {
-  DrawMaskedBorderExt(redraw_mask, FALSE);
+  DrawMaskedBorderExt(redraw_mask, DRAW_BORDER_TO_BACKBUFFER);
 }
 
-void DrawMaskedBorderToScreen(int redraw_mask)
+void DrawMaskedBorderToScreen(int draw_target)
 {
-  DrawMaskedBorderExt(redraw_mask, TRUE);
+  DrawMaskedBorderExt(REDRAW_ALL, draw_target);
 }
 
 void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
@@ -462,10 +468,54 @@ void DrawFramesPerSecond()
              font_nr, BLIT_OPAQUE);
 }
 
+#if DEBUG_FRAME_TIME
+static void PrintFrameTimeDebugging()
+{
+  static unsigned int last_counter = 0;
+  unsigned int counter = Counter();
+  int diff_1 = counter - last_counter;
+  int diff_2 = diff_1 - GAME_FRAME_DELAY;
+  int diff_2_max = 20;
+  int diff_2_cut = MIN(ABS(diff_2), diff_2_max);
+  char diff_bar[2 * diff_2_max + 5];
+  int pos = 0;
+  int i;
+
+  diff_bar[pos++] = (diff_2 < -diff_2_max ? '<' : ' ');
+
+  for (i = 0; i < diff_2_max; i++)
+    diff_bar[pos++] = (diff_2 >= 0 ? ' ' :
+                      i >= diff_2_max - diff_2_cut ? '-' : ' ');
+
+  diff_bar[pos++] = '|';
+
+  for (i = 0; i < diff_2_max; i++)
+    diff_bar[pos++] = (diff_2 <= 0 ? ' ' : i < diff_2_cut ? '+' : ' ');
+
+  diff_bar[pos++] = (diff_2 > diff_2_max ? '>' : ' ');
+
+  diff_bar[pos++] = '\0';
+
+  Error(ERR_INFO, "%06d [%02d] [%c%02d] %s",
+       counter,
+       diff_1,
+       (diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2),
+       diff_bar);
+
+  last_counter = counter;
+}
+#endif
+
 void BackToFront()
 {
+  static int last_redraw_mask = REDRAW_NONE;
+
+  // force screen redraw in every frame to continue drawing global animations
+  // (but always use the last redraw mask to prevent unwanted side effects)
   if (redraw_mask == REDRAW_NONE)
-    return;
+    redraw_mask = last_redraw_mask;
+
+  last_redraw_mask = redraw_mask;
 
 #if 1
   // masked border now drawn immediately when blitting backbuffer to window
@@ -509,6 +559,10 @@ void BackToFront()
   }
 
   redraw_mask = REDRAW_NONE;
+
+#if DEBUG_FRAME_TIME
+  PrintFrameTimeDebugging();
+#endif
 }
 
 static void FadeCrossSaveBackbuffer()
@@ -628,8 +682,33 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type)
   redraw_mask &= ~fade_mask;
 }
 
+static void SetScreenStates_BeforeFadingIn()
+{
+}
+
+static void SetScreenStates_AfterFadingIn()
+{
+  global.anim_status = global.anim_status_next;
+
+  // force update of global animation status in case of rapid screen changes
+  redraw_mask = REDRAW_ALL;
+  BackToFront();
+}
+
+static void SetScreenStates_BeforeFadingOut()
+{
+  global.anim_status = GAME_MODE_PSEUDO_FADING;
+}
+
+static void SetScreenStates_AfterFadingOut()
+{
+  global.border_status = game_status;
+}
+
 void FadeIn(int fade_mask)
 {
+  SetScreenStates_BeforeFadingIn();
+
 #if 1
   DrawMaskedBorder(REDRAW_ALL);
 #endif
@@ -644,12 +723,12 @@ void FadeIn(int fade_mask)
   FADE_SXSIZE = FULL_SXSIZE;
   FADE_SYSIZE = FULL_SYSIZE;
 
-  global.anim_status = global.anim_status_next;
+  SetScreenStates_AfterFadingIn();
 }
 
 void FadeOut(int fade_mask)
 {
-  global.anim_status = GAME_MODE_PSEUDO_FADING;
+  SetScreenStates_BeforeFadingOut();
 
 #if 0
   DrawMaskedBorder(REDRAW_ALL);
@@ -660,7 +739,7 @@ void FadeOut(int fade_mask)
   else
     FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
 
-  global.border_status = game_status;
+  SetScreenStates_AfterFadingOut();
 }
 
 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
@@ -4168,7 +4247,7 @@ unsigned int MoveDoor(unsigned int door_state)
     { DX, DY, DXSIZE, DYSIZE },
     { VX, VY, VXSIZE, VYSIZE }
   };
-  static int door1 = DOOR_OPEN_1;
+  static int door1 = DOOR_CLOSE_1;
   static int door2 = DOOR_CLOSE_2;
   unsigned int door_delay = 0;
   unsigned int door_delay_value;