added empty borders between different virtual buttons
[rocksndiamonds.git] / src / libgame / sdl.c
index f94193127f5eafb7cf5127d9bd00809c6ce6bc26..0fd3aa62eb6a319d7523357ce0419e4b2d0f455f 100644 (file)
@@ -17,6 +17,8 @@
 
 #define ENABLE_UNUSED_CODE     0       /* currently unused functions */
 
+#define DEBUG_JOYSTICKS                0
+
 
 /* ========================================================================= */
 /* video functions                                                           */
@@ -60,6 +62,10 @@ static void FinalizeScreen(int draw_target)
   // copy global animations to render target buffer, if defined (above border)
   if (gfx.draw_global_anim_function != NULL)
     gfx.draw_global_anim_function(draw_target, DRAW_GLOBAL_ANIM_STAGE_2);
+
+  // copy tile selection cursor to render target buffer, if defined (above all)
+  if (gfx.draw_tile_cursor_function != NULL)
+    gfx.draw_tile_cursor_function(draw_target);
 }
 
 static void UpdateScreenExt(SDL_Rect *rect, boolean with_frame_delay)
@@ -532,11 +538,7 @@ inline static void SDLInitVideoBuffer_VideoBuffer(boolean fullscreen)
   SDLSetWindowIcon(program.icon_filename);
 
   /* set window and icon title */
-#if defined(TARGET_SDL2)
-  SDL_SetWindowTitle(sdl_window, program.window_title);
-#else
-  SDL_WM_SetCaption(program.window_title, program.window_title);
-#endif
+  SDLSetWindowTitle();
 }
 
 inline static void SDLInitVideoBuffer_DrawBuffer()
@@ -830,6 +832,9 @@ boolean SDLSetVideoMode(boolean fullscreen)
 void SDLSetWindowTitle()
 {
 #if defined(TARGET_SDL2)
+  if (sdl_window == NULL)
+    return;
+
   SDL_SetWindowTitle(sdl_window, program.window_title);
 #else
   SDL_WM_SetCaption(program.window_title, program.window_title);
@@ -2535,7 +2540,7 @@ void SDLCloseAudio(void)
 /* event functions                                                           */
 /* ========================================================================= */
 
-void SDLNextEvent(Event *event)
+void SDLWaitEvent(Event *event)
 {
   SDL_WaitEvent(event);
 }
@@ -2616,7 +2621,7 @@ void SDLClearJoystickState()
   }
 }
 
-static boolean SDLOpenJoystick(int nr)
+boolean SDLOpenJoystick(int nr)
 {
   if (nr < 0 || nr >= MAX_PLAYERS)
     return FALSE;
@@ -2627,7 +2632,7 @@ static boolean SDLOpenJoystick(int nr)
   sdl_is_controller[nr] = FALSE;
 #endif
 
-#if 1
+#if DEBUG_JOYSTICKS
   Error(ERR_DEBUG, "opening joystick %d (%s)",
        nr, (sdl_is_controller[nr] ? "game controller" : "joystick"));
 #endif
@@ -2644,12 +2649,12 @@ static boolean SDLOpenJoystick(int nr)
   return (sdl_joystick[nr] != NULL);
 }
 
-static void SDLCloseJoystick(int nr)
+void SDLCloseJoystick(int nr)
 {
   if (nr < 0 || nr >= MAX_PLAYERS)
     return;
 
-#if 1
+#if DEBUG_JOYSTICKS
   Error(ERR_DEBUG, "closing joystick %d", nr);
 #endif
 
@@ -2749,7 +2754,7 @@ void HandleJoystickEvent(Event *event)
   {
 #if defined(TARGET_SDL2)
     case SDL_CONTROLLERDEVICEADDED:
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_CONTROLLERDEVICEADDED: device %d added",
            event->cdevice.which);
 #endif
@@ -2757,7 +2762,7 @@ void HandleJoystickEvent(Event *event)
       break;
 
     case SDL_CONTROLLERDEVICEREMOVED:
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_CONTROLLERDEVICEREMOVED: device %d removed",
            event->cdevice.which);
 #endif
@@ -2765,7 +2770,7 @@ void HandleJoystickEvent(Event *event)
       break;
 
     case SDL_CONTROLLERAXISMOTION:
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_CONTROLLERAXISMOTION: device %d, axis %d: %d",
            event->caxis.which, event->caxis.axis, event->caxis.value);
 #endif
@@ -2775,7 +2780,7 @@ void HandleJoystickEvent(Event *event)
       break;
 
     case SDL_CONTROLLERBUTTONDOWN:
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONDOWN: device %d, button %d",
            event->cbutton.which, event->cbutton.button);
 #endif
@@ -2785,7 +2790,7 @@ void HandleJoystickEvent(Event *event)
       break;
 
     case SDL_CONTROLLERBUTTONUP:
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONUP: device %d, button %d",
            event->cbutton.which, event->cbutton.button);
 #endif
@@ -2799,7 +2804,7 @@ void HandleJoystickEvent(Event *event)
       if (sdl_is_controller[event->jaxis.which])
        break;
 
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_JOYAXISMOTION: device %d, axis %d: %d",
            event->jaxis.which, event->jaxis.axis, event->jaxis.value);
 #endif
@@ -2813,7 +2818,7 @@ void HandleJoystickEvent(Event *event)
       if (sdl_is_controller[event->jaxis.which])
        break;
 
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_JOYBUTTONDOWN: device %d, button %d",
            event->jbutton.which, event->jbutton.button);
 #endif
@@ -2827,7 +2832,7 @@ void HandleJoystickEvent(Event *event)
       if (sdl_is_controller[event->jaxis.which])
        break;
 
-#if 1
+#if DEBUG_JOYSTICKS
       Error(ERR_DEBUG, "SDL_JOYBUTTONUP: device %d, button %d",
            event->jbutton.which, event->jbutton.button);
 #endif
@@ -2847,7 +2852,7 @@ void SDLInitJoysticks()
   static boolean sdl_joystick_subsystem_initialized = FALSE;
   boolean print_warning = !sdl_joystick_subsystem_initialized;
 #if defined(TARGET_SDL2)
-  char *mappings_file_base = getPath2(options.ro_base_directory,
+  char *mappings_file_base = getPath2(options.conf_directory,
                                      GAMECONTROLLER_BASENAME);
   char *mappings_file_user = getPath2(getUserGameDataDir(),
                                      GAMECONTROLLER_BASENAME);
@@ -2874,23 +2879,30 @@ void SDLInitJoysticks()
 #if defined(TARGET_SDL2)
     num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file_base);
 
-    if (num_mappings != -1)
-      Error(ERR_INFO, "%d game controller base mapping(s) added", num_mappings);
-    else
+    /* the included game controller base mappings should always be found */
+    if (num_mappings == -1)
       Error(ERR_WARN, "no game controller base mappings found");
+#if DEBUG_JOYSTICKS
+    else
+      Error(ERR_INFO, "%d game controller base mapping(s) added", num_mappings);
+#endif
 
     num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file_user);
 
-    if (num_mappings != -1)
-      Error(ERR_INFO, "%d game controller user mapping(s) added", num_mappings);
-    else
+#if DEBUG_JOYSTICKS
+    /* the personal game controller user mappings may or may not be found */
+    if (num_mappings == -1)
       Error(ERR_WARN, "no game controller user mappings found");
+    else
+      Error(ERR_INFO, "%d game controller user mapping(s) added", num_mappings);
 
     Error(ERR_INFO, "%d joystick(s) found:", SDL_NumJoysticks());
+#endif
 
     checked_free(mappings_file_base);
     checked_free(mappings_file_user);
 
+#if DEBUG_JOYSTICKS
     for (i = 0; i < SDL_NumJoysticks(); i++)
     {
       const char *name, *type;
@@ -2909,6 +2921,7 @@ void SDLInitJoysticks()
       Error(ERR_INFO, "- joystick %d (%s): '%s'",
            i, type, (name ? name : "(Unknown)"));
     }
+#endif
 #endif
   }
 
@@ -2965,16 +2978,134 @@ boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
   return TRUE;
 }
 
+
+/* ========================================================================= */
+/* touch input overlay functions                                             */
+/* ========================================================================= */
+
 #if defined(USE_TOUCH_INPUT_OVERLAY)
+static void DrawTouchInputOverlay_ShowGrid(int alpha)
+{
+  SDL_Rect rect;
+  int grid_xsize = overlay.grid_xsize;
+  int grid_ysize = overlay.grid_ysize;
+  int x, y;
+
+  SDL_SetRenderDrawColor(sdl_renderer, 255, 255, 255, alpha);
+  SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
+
+  for (x = 0; x < grid_xsize; x++)
+  {
+    rect.x = (x + 0) * video.screen_width / grid_xsize;
+    rect.w = (x + 1) * video.screen_width / grid_xsize - rect.x;
+
+    for (y = 0; y < grid_ysize; y++)
+    {
+      rect.y = (y + 0) * video.screen_height / grid_ysize;
+      rect.h = (y + 1) * video.screen_height / grid_ysize - rect.y;
+
+      if (overlay.grid_button[x][y] == CHAR_GRID_BUTTON_NONE)
+       SDL_RenderDrawRect(sdl_renderer, &rect);
+    }
+  }
+
+  SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
+}
+
+static void DrawTouchInputOverlay_ShowGridButtons(int alpha)
+{
+  static int alpha_max = SDL_ALPHA_OPAQUE / 2;
+  static int alpha_step = 5;
+  static int alpha_direction = 0;
+  static int alpha_highlight = 0;
+  SDL_Rect rect;
+  int grid_xsize = overlay.grid_xsize;
+  int grid_ysize = overlay.grid_ysize;
+  int x, y;
+
+  if (alpha == alpha_max)
+  {
+    if (alpha_direction < 0)
+    {
+      alpha_highlight = MAX(0, alpha_highlight - alpha_step);
+
+      if (alpha_highlight == 0)
+       alpha_direction = 1;
+    }
+    else
+    {
+      alpha_highlight = MIN(alpha_highlight + alpha_step, alpha_max);
+
+      if (alpha_highlight == alpha_max)
+       alpha_direction = -1;
+    }
+  }
+  else
+  {
+    alpha_direction = 1;
+    alpha_highlight = alpha;
+  }
+
+  SDL_SetRenderDrawBlendMode(sdl_renderer, SDL_BLENDMODE_BLEND);
+
+  for (x = 0; x < grid_xsize; x++)
+  {
+    for (y = 0; y < grid_ysize; y++)
+    {
+      rect.x = (x + 0) * video.screen_width  / grid_xsize;
+      rect.y = (y + 0) * video.screen_height / grid_ysize;
+      rect.w = (x + 1) * video.screen_width  / grid_xsize - rect.x;
+      rect.h = (y + 1) * video.screen_height / grid_ysize - rect.y;
+
+      if (x == 0 ||
+         overlay.grid_button[x - 1][y] != overlay.grid_button[x][y])
+      {
+       rect.x += 2;
+       rect.w -= 2;
+      }
+
+      if (x == grid_xsize - 1 ||
+         overlay.grid_button[x + 1][y] != overlay.grid_button[x][y])
+      {
+       rect.w -= 2;
+      }
+
+      if (y == 0 ||
+         overlay.grid_button[x][y - 1] != overlay.grid_button[x][y])
+      {
+       rect.y += 2;
+       rect.h -= 2;
+      }
+
+      if (y == grid_ysize - 1 ||
+         overlay.grid_button[x][y + 1] != overlay.grid_button[x][y])
+      {
+       rect.h -= 2;
+      }
+
+      if (overlay.grid_button[x][y] == overlay.grid_button_highlight)
+       SDL_SetRenderDrawColor(sdl_renderer, 255, 255, 255, alpha_highlight);
+      else
+       SDL_SetRenderDrawColor(sdl_renderer, 255, 255, 255, alpha);
+
+      if (overlay.grid_button[x][y] != CHAR_GRID_BUTTON_NONE)
+       SDL_RenderFillRect(sdl_renderer, &rect);
+    }
+  }
+
+  SDL_SetRenderDrawColor(sdl_renderer, 0, 0, 0, 255);
+}
+
 static void DrawTouchInputOverlay()
 {
   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_max = SDL_ALPHA_OPAQUE / 2;
   static int alpha_step = 5;
-  static int alpha_last = 0;
+  static int alpha_last = -1;
   static int alpha = 0;
   boolean active = (overlay.enabled && overlay.active);
 
@@ -2996,6 +3127,21 @@ static void DrawTouchInputOverlay()
       deactivated = TRUE;
   }
 
+  if (overlay.show_grid)
+    show_grid = TRUE;
+  else if (deactivated)
+    show_grid = FALSE;
+
+  if (show_grid)
+    DrawTouchInputOverlay_ShowGrid(alpha);
+
+  DrawTouchInputOverlay_ShowGridButtons(alpha);
+
+  return;
+
+
+  // !!! VIRTUAL BUTTONS FROM IMAGE FILE NOT USED ANYMORE !!!
+
   if (!initialized)
   {
     char *basename = "overlay/VirtualButtons.png";
@@ -3024,7 +3170,6 @@ static void DrawTouchInputOverlay()
     SDL_FreeSurface(surface);
 
     SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
-    SDL_SetTextureAlphaMod(texture, alpha_max);
 
     initialized = TRUE;
   }