added using setup option for displaying overlay touch buttons
[rocksndiamonds.git] / src / tools.c
index 0872e24bc1fde98a5459eff7dda8fff43ae68293..79cf0885135681310694fdc4dc562fd40dfa5cf0 100644 (file)
@@ -512,6 +512,10 @@ static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height,
   Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status);
   Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr;
 
+  // may happen for "border.draw_masked.*" with undefined "global.border.*"
+  if (src_bitmap == NULL)
+    return;
+
   if (x == -1 && y == -1)
     return;
 
@@ -1091,6 +1095,13 @@ void FadeSkipNextFadeOut(void)
   FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
 }
 
+static int getGlobalGameStatus(int status)
+{
+  return (status == GAME_MODE_PSEUDO_TYPENAME ? GAME_MODE_MAIN :
+         status == GAME_MODE_SCOREINFO       ? GAME_MODE_SCORES :
+         status);
+}
+
 static Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
 {
   if (graphic == IMG_UNDEFINED)
@@ -1113,14 +1124,14 @@ static Bitmap *getGlobalBorderBitmap(int graphic)
   return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
 }
 
-Bitmap *getGlobalBorderBitmapFromStatus(int status)
+Bitmap *getGlobalBorderBitmapFromStatus(int status_raw)
 {
+  int status = getGlobalGameStatus(status_raw);
   int graphic =
-    (status == GAME_MODE_MAIN ||
-     status == GAME_MODE_PSEUDO_TYPENAME       ? IMG_GLOBAL_BORDER_MAIN :
-     status == GAME_MODE_SCORES                        ? IMG_GLOBAL_BORDER_SCORES :
-     status == GAME_MODE_EDITOR                        ? IMG_GLOBAL_BORDER_EDITOR :
-     status == GAME_MODE_PLAYING               ? IMG_GLOBAL_BORDER_PLAYING :
+    (status == GAME_MODE_MAIN    ? IMG_GLOBAL_BORDER_MAIN :
+     status == GAME_MODE_SCORES  ? IMG_GLOBAL_BORDER_SCORES :
+     status == GAME_MODE_EDITOR  ? IMG_GLOBAL_BORDER_EDITOR :
+     status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
      IMG_GLOBAL_BORDER);
 
   return getGlobalBorderBitmap(graphic);
@@ -1490,8 +1501,9 @@ int getGraphicAnimationFrameXY(int graphic, int lx, int ly)
     int ysize = MAX(1, g->anim_frames / xsize);
     int xoffset = g->anim_start_frame % xsize;
     int yoffset = g->anim_start_frame % ysize;
-    int x = (lx + xoffset + xsize) % xsize;
-    int y = (ly + yoffset + ysize) % ysize;
+    // may be needed if screen field is significantly larger than playfield
+    int x = (lx + xoffset + SCR_FIELDX * xsize) % xsize;
+    int y = (ly + yoffset + SCR_FIELDY * ysize) % ysize;
     int sync_frame = y * xsize + x;
 
     return sync_frame % g->anim_frames;
@@ -1499,14 +1511,19 @@ int getGraphicAnimationFrameXY(int graphic, int lx, int ly)
   else if (graphic_info[graphic].anim_mode & ANIM_RANDOM_STATIC)
   {
     struct GraphicInfo *g = &graphic_info[graphic];
-    int x = (lx + lev_fieldx) % lev_fieldx;
-    int y = (ly + lev_fieldy) % lev_fieldy;
+    // may be needed if screen field is significantly larger than playfield
+    int x = (lx + SCR_FIELDX * lev_fieldx) % lev_fieldx;
+    int y = (ly + SCR_FIELDY * lev_fieldy) % lev_fieldy;
     int sync_frame = GfxRandomStatic[x][y];
 
     return sync_frame % g->anim_frames;
   }
+  else
+  {
+    int sync_frame = (IN_LEV_FIELD(lx, ly) ? GfxFrame[lx][ly] : -1);
 
-  return getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+    return getGraphicAnimationFrame(graphic, sync_frame);
+  }
 }
 
 void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
@@ -1996,11 +2013,11 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
   int graphic;
   int frame;
 
-  if (element == EL_EMPTY)
-    element = GfxElementEmpty[lx][ly];
-
   if (IN_LEV_FIELD(lx, ly))
   {
+    if (element == EL_EMPTY)
+      element = GfxElementEmpty[lx][ly];
+
     SetRandomAnimationValue(lx, ly);
 
     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
@@ -2517,6 +2534,11 @@ void DrawScreenGraphic(int x, int y, int graphic, int frame)
   }
 }
 
+void DrawLevelGraphic(int x, int y, int graphic, int frame)
+{
+  DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+}
+
 void DrawScreenElement(int x, int y, int element)
 {
   int mask_mode = NO_MASKING;
@@ -2903,11 +2925,11 @@ static void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
       for (xx = 0; xx < xsize; xx++)
        DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
 
-    DrawTextBuffer(sx + font_width, sy + font_height,
-                  level.envelope[envelope_nr].text, font_nr, max_xsize,
-                  xsize - 2, ysize - 2, 0, mask_mode,
-                  level.envelope[envelope_nr].autowrap,
-                  level.envelope[envelope_nr].centered, FALSE);
+    DrawTextArea(sx + font_width, sy + font_height,
+                level.envelope[envelope_nr].text, font_nr, max_xsize,
+                xsize - 2, ysize - 2, 0, mask_mode,
+                level.envelope[envelope_nr].autowrap,
+                level.envelope[envelope_nr].centered, FALSE);
 
     redraw_mask |= REDRAW_FIELD;
     BackToFront();
@@ -5835,6 +5857,10 @@ void CreateToolButtons(void)
     int y = pos->y;
     int id = i;
 
+    // do not use touch buttons if overlay touch buttons are disabled
+    if (is_touch_button && !setup.touch.overlay_buttons)
+      continue;
+
     if (global.use_envelope_request && !is_touch_button)
     {
       setRequestPosition(&base_x, &base_y, TRUE);
@@ -9724,9 +9750,9 @@ void ChangeViewportPropertiesIfNeeded(void)
 {
   boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
                               FALSE : setup.small_game_graphics);
-  int gfx_game_mode = game_status;
-  int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
-                       game_status);
+  int gfx_game_mode = getGlobalGameStatus(game_status);
+  int gfx_game_mode2 = (gfx_game_mode == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+                       gfx_game_mode);
   struct RectWithBorder *vp_window    = &viewport.window[gfx_game_mode];
   struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
   struct RectWithBorder *vp_door_1    = &viewport.door_1[gfx_game_mode];
@@ -9939,12 +9965,22 @@ void ChangeViewportPropertiesIfNeeded(void)
   }
 }
 
+void OpenURL(char *url)
+{
+  SDL_OpenURL(url);
+}
+
+void OpenURLFromHash(SetupFileHash *hash, int hash_key)
+{
+  OpenURL(getHashEntry(hash, int2str(hash_key, 0)));
+}
+
 
 // ============================================================================
 // tests
 // ============================================================================
 
-#if defined(PLATFORM_WIN32)
+#if defined(PLATFORM_WINDOWS)
 /* FILETIME of Jan 1 1970 00:00:00. */
 static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);
 
@@ -9998,7 +10034,7 @@ static char *test_init_uuid_random_function_better(void)
   return seed_text;
 }
 
-#if defined(PLATFORM_WIN32)
+#if defined(PLATFORM_WINDOWS)
 static char *test_init_uuid_random_function_better_windows(void)
 {
   static char seed_text[100];
@@ -10026,7 +10062,7 @@ static unsigned int test_uuid_random_function_better(int max)
   return (max > 0 ? prng_get_uint() % max : 0);
 }
 
-#if defined(PLATFORM_WIN32)
+#if defined(PLATFORM_WINDOWS)
 #define NUM_UUID_TESTS                 3
 #else
 #define NUM_UUID_TESTS                 2
@@ -10053,7 +10089,7 @@ static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids)
      test_uuid_random_function_better);
   int xpos = 40;
 
-#if defined(PLATFORM_WIN32)
+#if defined(PLATFORM_WINDOWS)
   if (nr == 2)
   {
     random_name = "windows";