changed "http" to "https" in URLs
[rocksndiamonds.git] / src / libgame / sdl.c
index a4fc6fa09d0d6c6465606f2ef808c40e209e013e..990054de955f965cab82e6c66936b1aaf63ac17f 100644 (file)
@@ -4,7 +4,7 @@
 // (c) 1995-2014 by Artsoft Entertainment
 //                         Holger Schemel
 //                 info@artsoft.org
-//                 http://www.artsoft.org/
+//                 https://www.artsoft.org/
 // ----------------------------------------------------------------------------
 // sdl.c
 // ============================================================================
@@ -14,6 +14,7 @@
 #include "joystick.h"
 #include "misc.h"
 #include "setup.h"
+#include "gadgets.h"
 
 #define ENABLE_UNUSED_CODE     0       // currently unused functions
 
@@ -38,7 +39,8 @@ void sge_Line(SDL_Surface *, Sint16, Sint16, Sint16, Sint16, Uint32);
 
 #if defined(USE_TOUCH_INPUT_OVERLAY)
 // functions to draw overlay graphics for touch device input
-static void DrawTouchInputOverlay();
+static void DrawTouchInputOverlay(void);
+static void DrawTouchGadgetsOverlay(void);
 #endif
 
 void SDLLimitScreenUpdates(boolean enable)
@@ -212,18 +214,25 @@ static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
 #if defined(USE_TOUCH_INPUT_OVERLAY)
   // draw overlay graphics for touch device input, if needed
   DrawTouchInputOverlay();
+
+  // draw overlay gadgets for touch device input, if needed
+  DrawTouchGadgetsOverlay();
 #endif
 
   // global synchronization point of the game to align video frame delay
   if (with_frame_delay)
     WaitUntilDelayReached(&video.frame_delay, video.frame_delay_value);
 
+  video.frame_counter++;
+
   // show render target buffer on screen
   SDL_RenderPresent(sdl_renderer);
 }
 
 static void UpdateScreen_WithFrameDelay(SDL_Rect *rect)
 {
+  PumpEvents();                // execute event filter actions while waiting
+
   UpdateScreenExt(rect, TRUE);
 }
 
@@ -264,7 +273,7 @@ static void SDLSetWindowIcon(char *basename)
 
   if ((surface = IMG_Load(filename)) == NULL)
   {
-    Error(ERR_WARN, "IMG_Load() failed: %s", SDL_GetError());
+    Error(ERR_WARN, "IMG_Load('%s') failed: %s", basename, SDL_GetError());
 
     return;
   }
@@ -321,6 +330,15 @@ static void SDLSetAlpha(SDL_Surface *surface, boolean set, int alpha)
   SDL_SetSurfaceAlphaMod(surface, alpha);
 }
 
+const char *SDLGetRendererName(void)
+{
+  static SDL_RendererInfo renderer_info;
+
+  SDL_GetRendererInfo(sdl_renderer, &renderer_info);
+
+  return renderer_info.name;
+}
+
 SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
 {
   SDL_PixelFormat format;
@@ -344,6 +362,11 @@ SDL_Surface *SDLGetNativeSurface(SDL_Surface *surface)
   if (new_surface == NULL)
     Error(ERR_EXIT, "SDL_ConvertSurface() failed: %s", SDL_GetError());
 
+  // workaround for a bug in SDL 2.0.12 (which does not convert the color key)
+  if (SDLHasColorKey(surface) && !SDLHasColorKey(new_surface))
+    SDL_SetColorKey(new_surface, SET_TRANSPARENT_PIXEL,
+                   SDLGetColorKey(surface));
+
   return new_surface;
 }
 
@@ -483,7 +506,7 @@ static boolean SDLCreateScreen(boolean fullscreen)
 {
   SDL_Surface *new_surface = NULL;
 
-  int surface_flags_window     = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
+  int surface_flags_window     = SURFACE_FLAGS;
   int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
 
 #if 1
@@ -496,8 +519,6 @@ static boolean SDLCreateScreen(boolean fullscreen)
   int renderer_flags = SDL_RENDERER_SOFTWARE;
 #endif
 
-  SDLSetScreenSizeAndOffsets(video.width, video.height);
-
   int width  = video.width;
   int height = video.height;
   int screen_width  = video.screen_width;
@@ -559,7 +580,6 @@ static boolean SDLCreateScreen(boolean fullscreen)
 
     if (sdl_renderer != NULL)
     {
-      SDL_RenderSetLogicalSize(sdl_renderer, screen_width, screen_height);
       // SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
       SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, setup.window_scaling_quality);
 
@@ -599,6 +619,8 @@ static boolean SDLCreateScreen(boolean fullscreen)
     Error(ERR_WARN, "SDL_CreateWindow() failed: %s", SDL_GetError());
   }
 
+  SDLSetScreenProperties();
+
   // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
   if (new_surface != NULL)
     fullscreen_enabled = fullscreen;
@@ -660,32 +682,6 @@ boolean SDLSetVideoMode(boolean fullscreen)
 
   SDLRedrawWindow();                   // map window
 
-#ifdef DEBUG
-#if defined(PLATFORM_WIN32)
-  // experimental drag and drop code
-
-  SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
-
-  {
-    SDL_SysWMinfo wminfo;
-    HWND hwnd;
-    boolean wminfo_success = FALSE;
-
-    SDL_VERSION(&wminfo.version);
-
-    if (sdl_window)
-      wminfo_success = SDL_GetWindowWMInfo(sdl_window, &wminfo);
-
-    if (wminfo_success)
-    {
-      hwnd = wminfo.info.win.window;
-
-      DragAcceptFiles(hwnd, TRUE);
-    }
-  }
-#endif
-#endif
-
   return success;
 }
 
@@ -779,17 +775,34 @@ void SDLSetWindowFullscreen(boolean fullscreen)
 
 void SDLSetDisplaySize(void)
 {
-  SDL_Rect display_bounds;
+  if (sdl_renderer != NULL)
+  {
+    int w, h;
+
+    SDL_GetRendererOutputSize(sdl_renderer, &w, &h);
+
+    video.display_width  = w;
+    video.display_height = h;
+
+#if 0
+    Error(ERR_DEBUG, "SDL renderer size: %d x %d",
+         video.display_width, video.display_height);
+#endif
+  }
+  else
+  {
+    SDL_Rect display_bounds;
 
-  SDL_GetDisplayBounds(0, &display_bounds);
+    SDL_GetDisplayBounds(0, &display_bounds);
 
-  video.display_width  = display_bounds.w;
-  video.display_height = display_bounds.h;
+    video.display_width  = display_bounds.w;
+    video.display_height = display_bounds.h;
 
 #if 0
-  Error(ERR_DEBUG, "SDL real screen size: %d x %d",
-       video.display_width, video.display_height);
+    Error(ERR_DEBUG, "SDL display size: %d x %d",
+         video.display_width, video.display_height);
 #endif
+  }
 }
 
 void SDLSetScreenSizeAndOffsets(int width, int height)
@@ -833,6 +846,7 @@ void SDLSetScreenSizeForRenderer(int width, int height)
 
 void SDLSetScreenProperties(void)
 {
+  SDLSetDisplaySize();
   SDLSetScreenSizeAndOffsets(video.width, video.height);
   SDLSetScreenSizeForRenderer(video.screen_width, video.screen_height);
 }
@@ -1045,6 +1059,17 @@ void SDLFadeRectangle(int x, int y, int width, int height,
 
   time_current = SDL_GetTicks();
 
+  if (fade_delay <= 0)
+  {
+    // immediately draw final target frame without delay
+    fade_mode &= (FADE_MODE_FADE | FADE_MODE_TRANSFORM);
+    fade_delay = 1;
+    time_current -= 1;
+
+    // when fading without delay, also skip post delay
+    post_delay = 0;
+  }
+
   if (fade_mode == FADE_MODE_MELT)
   {
     boolean done = FALSE;
@@ -2256,7 +2281,8 @@ Bitmap *SDLLoadImage(char *filename)
 
   // load image to temporary surface
   if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
-    Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
+    Error(ERR_EXIT, "IMG_Load('%s') failed: %s", getBaseNamePtr(filename),
+         SDL_GetError());
 
   print_timestamp_time("IMG_Load");
 
@@ -2388,38 +2414,25 @@ void SDLWaitEvent(Event *event)
   SDL_WaitEvent(event);
 }
 
-void SDLHandleWindowManagerEvent(Event *event)
+void SDLCorrectRawMousePosition(int *x, int *y)
 {
-#ifdef DEBUG
-#if defined(PLATFORM_WIN32)
-  // experimental drag and drop code
-
-  SDL_SysWMEvent *syswmevent = (SDL_SysWMEvent *)event;
-  SDL_SysWMmsg *syswmmsg = (SDL_SysWMmsg *)(syswmevent->msg);
-
-  if (syswmmsg->msg.win.msg == WM_DROPFILES)
-  {
-    HDROP hdrop = (HDROP)syswmmsg->msg.win.wParam;
-    int i, num_files;
+  if (sdl_renderer == NULL)
+    return;
 
-    printf("::: SDL_SYSWMEVENT:\n");
+  // this corrects the raw mouse position for logical screen size within event
+  // filters (correction done later by SDL library when handling mouse events)
 
-    num_files = DragQueryFile(hdrop, 0xffffffff, NULL, 0);
+  SDL_Rect viewport;
+  float scale_x, scale_y;
 
-    for (i = 0; i < num_files; i++)
-    {
-      int buffer_len = DragQueryFile(hdrop, i, NULL, 0);
-      char buffer[buffer_len + 1];
+  SDL_RenderGetViewport(sdl_renderer, &viewport);
+  SDL_RenderGetScale(sdl_renderer, &scale_x, &scale_y);
 
-      DragQueryFile(hdrop, i, buffer, buffer_len + 1);
+  *x = (int)(*x / scale_x);
+  *y = (int)(*y / scale_y);
 
-      printf("::: - '%s'\n", buffer);
-    }
-
-    DragFinish((HDROP)syswmmsg->msg.win.wParam);
-  }
-#endif
-#endif
+  *x -= viewport.x;
+  *y -= viewport.y;
 }
 
 
@@ -2553,7 +2566,10 @@ static void setJoystickButton(int nr, int button_id_raw, int button_state)
 
 void HandleJoystickEvent(Event *event)
 {
-  switch(event->type)
+  // when using joystick, disable overlay touch buttons
+  runtime.uses_touch_device = FALSE;
+
+  switch (event->type)
   {
     case SDL_CONTROLLERDEVICEADDED:
 #if DEBUG_JOYSTICKS
@@ -2864,7 +2880,10 @@ static void DrawTouchInputOverlay_ShowGridButtons(int alpha)
        continue;
 
       if (grid_button == overlay.grid_button_highlight)
-       alpha_draw = alpha_highlight;
+      {
+       draw_outlined = FALSE;
+       alpha_draw = MIN((float)alpha_highlight * 1.5, SDL_ALPHA_OPAQUE);
+      }
 
       if (draw_pressed && overlay.grid_button_action & grid_button_action)
       {
@@ -2945,12 +2964,8 @@ static void DrawTouchInputOverlay_ShowGridButtons(int alpha)
 
 static void DrawTouchInputOverlay(void)
 {
-  static SDL_Texture *texture = NULL;
-  static boolean initialized = FALSE;
   static boolean deactivated = TRUE;
   static boolean show_grid = FALSE;
-  static int width = 0, height = 0;
-  static int alpha_last = -1;
   static int alpha = 0;
   int alpha_max = ALPHA_FROM_TRANSPARENCY(setup.touch.transparency);
   int alpha_step = ALPHA_FADING_STEPSIZE(alpha_max);
@@ -2983,72 +2998,10 @@ static void DrawTouchInputOverlay(void)
     DrawTouchInputOverlay_ShowGrid(alpha);
 
   DrawTouchInputOverlay_ShowGridButtons(alpha);
+}
 
-  return;
-
-
-  // !!! VIRTUAL BUTTONS FROM IMAGE FILE NOT USED ANYMORE !!!
-
-  if (!initialized)
-  {
-    char *basename = "overlay/VirtualButtons.png";
-    char *filename = getCustomImageFilename(basename);
-
-    if (filename == NULL)
-      Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
-
-    SDL_Surface *surface;
-
-    if ((surface = IMG_Load(filename)) == NULL)
-      Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
-
-    width  = surface->w;
-    height = surface->h;
-
-    // set black pixel to transparent if no alpha channel / transparent color
-    if (!SDLHasAlpha(surface) &&
-       !SDLHasColorKey(surface))
-      SDL_SetColorKey(surface, SET_TRANSPARENT_PIXEL,
-                     SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
-
-    if ((texture = SDLCreateTextureFromSurface(surface)) == NULL)
-      Error(ERR_EXIT, "SDLCreateTextureFromSurface() failed");
-
-    SDL_FreeSurface(surface);
-
-    SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
-
-    initialized = TRUE;
-  }
-
-  if (alpha != alpha_last)
-    SDL_SetTextureAlphaMod(texture, alpha);
-
-  alpha_last = alpha;
-
-  float ratio_overlay = (float) width / height;
-  float ratio_screen = (float) video.screen_width / video.screen_height;
-  int width_scaled, height_scaled;
-  int xpos, ypos;
-
-  if (ratio_overlay > ratio_screen)
-  {
-    width_scaled = video.screen_width;
-    height_scaled = video.screen_height * ratio_screen / ratio_overlay;
-    xpos = 0;
-    ypos = video.screen_height - height_scaled;
-  }
-  else
-  {
-    width_scaled = video.screen_width * ratio_overlay / ratio_screen;
-    height_scaled = video.screen_height;
-    xpos = (video.screen_width - width_scaled) / 2;
-    ypos = 0;
-  }
-
-  SDL_Rect src_rect = { 0, 0, width, height };
-  SDL_Rect dst_rect = { xpos, ypos, width_scaled, height_scaled };
-
-  SDL_RenderCopy(sdl_renderer, texture, &src_rect, &dst_rect);
+static void DrawTouchGadgetsOverlay(void)
+{
+  DrawGadgets_OverlayTouchButtons();
 }
 #endif