fixed bug with not unmapping gadgets from previous screen on score info
[rocksndiamonds.git] / src / screens.c
index 4c361ae4d84b5550c83d82ec1124137f10f7149a..b5cef16637aba7a2cee5e1428b95cc5609d06fea 100644 (file)
 // screen gadget identifiers
 #define SCREEN_CTRL_ID_PREV_LEVEL      0
 #define SCREEN_CTRL_ID_NEXT_LEVEL      1
-#define SCREEN_CTRL_ID_FIRST_LEVEL     2
-#define SCREEN_CTRL_ID_LAST_LEVEL      3
-#define SCREEN_CTRL_ID_LEVEL_NUMBER    4
-#define SCREEN_CTRL_ID_PREV_PLAYER     5
-#define SCREEN_CTRL_ID_NEXT_PLAYER     6
-#define SCREEN_CTRL_ID_INSERT_SOLUTION 7
-#define SCREEN_CTRL_ID_PLAY_SOLUTION   8
-#define SCREEN_CTRL_ID_SWITCH_ECS_AGA  9
-#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE 10
-#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE 11
-#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE2        12
-#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE2        13
-#define SCREEN_CTRL_ID_SCROLL_UP       14
-#define SCREEN_CTRL_ID_SCROLL_DOWN     15
-#define SCREEN_CTRL_ID_SCROLL_VERTICAL 16
-#define SCREEN_CTRL_ID_NETWORK_SERVER  17
-
-#define NUM_SCREEN_GADGETS             18
-
-#define NUM_SCREEN_MENUBUTTONS         14
+#define SCREEN_CTRL_ID_PREV_LEVEL2     2
+#define SCREEN_CTRL_ID_NEXT_LEVEL2     3
+#define SCREEN_CTRL_ID_FIRST_LEVEL     4
+#define SCREEN_CTRL_ID_LAST_LEVEL      5
+#define SCREEN_CTRL_ID_LEVEL_NUMBER    6
+#define SCREEN_CTRL_ID_PREV_PLAYER     7
+#define SCREEN_CTRL_ID_NEXT_PLAYER     8
+#define SCREEN_CTRL_ID_INSERT_SOLUTION 9
+#define SCREEN_CTRL_ID_PLAY_SOLUTION   10
+#define SCREEN_CTRL_ID_SWITCH_ECS_AGA  11
+#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE 12
+#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE 13
+#define SCREEN_CTRL_ID_TOUCH_PREV_PAGE2        14
+#define SCREEN_CTRL_ID_TOUCH_NEXT_PAGE2        15
+#define SCREEN_CTRL_ID_SCROLL_UP       16
+#define SCREEN_CTRL_ID_SCROLL_DOWN     17
+#define SCREEN_CTRL_ID_SCROLL_VERTICAL 18
+#define SCREEN_CTRL_ID_NETWORK_SERVER  19
+
+#define NUM_SCREEN_GADGETS             20
+
+#define NUM_SCREEN_MENUBUTTONS         16
 #define NUM_SCREEN_SCROLLBUTTONS       2
 #define NUM_SCREEN_SCROLLBARS          1
 #define NUM_SCREEN_TEXTINPUT           1
 #define SCREEN_MASK_INPUT              (1 << 2)
 #define SCREEN_MASK_TOUCH              (1 << 3)
 #define SCREEN_MASK_TOUCH2             (1 << 4)
+#define SCREEN_MASK_SCORES             (1 << 5)
 
 // graphic position and size values for buttons and scrollbars
 #define SC_MENUBUTTON_XSIZE            TILEX
@@ -259,6 +262,7 @@ static void HandleChooseTree(int, int, int, int, int, TreeInfo **);
 static void DrawChoosePlayerName(void);
 static void DrawChooseLevelSet(void);
 static void DrawChooseLevelNr(void);
+static void DrawScoreInfo(int);
 static void DrawInfoScreen(void);
 static void DrawSetupScreen(void);
 static void DrawTypeName(void);
@@ -291,6 +295,7 @@ static boolean OfferUploadTapes(void);
 static void execOfferUploadTapes(void);
 
 static void DrawHallOfFame_setScoreEntries(void);
+static void HandleHallOfFame_SelectLevel(int, int);
 static char *getHallOfFameScoreText(int);
 
 static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
@@ -615,6 +620,8 @@ static int align_yoffset = 0;
 
 #define EXTRA_SPACING_SCORES(i)        (EXTRA_SPACING_INFO(i))
 
+#define EXTRA_SPACING_SCOREINFO(i) (menu.extra_spacing[GAME_MODE_SCOREINFO])
+
 #define DRAW_XOFFSET(s)                ((s) == GAME_MODE_INFO ?                \
                                 DRAW_XOFFSET_INFO(info_mode) :         \
                                 (s) == GAME_MODE_SETUP ?               \
@@ -4866,7 +4873,12 @@ static void DrawChooseTree(TreeInfo **ti_ptr)
 
   OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
 
+  // map gadgets for high score screen
+  if (game_status == GAME_MODE_SCORES)
+    MapScreenMenuGadgets(SCREEN_MASK_SCORES);
+
   MapScreenTreeGadgets(*ti_ptr);
+
   HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr);
 
   DrawMaskedBorder(fade_mask);
@@ -5133,6 +5145,9 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
   int num_entries = numTreeInfoInGroup(ti);
   int num_page_entries = MIN(num_entries, NUM_MENU_ENTRIES_ON_SCREEN);
   boolean position_set_by_scrollbar = (dx == 999);
+  boolean button_action = (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE);
+  boolean button_is_valid = (mx >= 0 && my >= 0);
+  boolean button_screen_clicked = (button_action && button_is_valid);
 
   if (game_status == GAME_MODE_SCORES)
   {
@@ -5160,7 +5175,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
       {
        drawChooseTreeScreen_Scores_NotAvailable();
       }
-      else if (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE)
+      else if (button_screen_clicked)
       {
        PlaySound(SND_MENU_ITEM_SELECTING);
 
@@ -5322,7 +5337,13 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
     y = ti->cl_cursor + dy;
   }
 
-  if (dx == 1)
+  if (game_status == GAME_MODE_SCORES && ABS(dx) == 1)
+  {
+    HandleHallOfFame_SelectLevel(1, dx);
+
+    return;
+  }
+  else if (dx == 1)
   {
     TreeInfo *node_first, *node_cursor;
     int entry_pos = ti->cl_first + y;
@@ -5546,6 +5567,14 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button,
                               level.random_seed);
              return;
            }
+           else
+           {
+             SetGameStatus(GAME_MODE_SCOREINFO);
+
+             DrawScoreInfo(node_cursor->pos);
+
+             return;
+           }
          }
 
          SetGameStatus(GAME_MODE_MAIN);
@@ -5754,14 +5783,8 @@ void DrawHallOfFame(int level_nr)
   DrawChooseTree(&score_entry_current);
 }
 
-static char *getHallOfFameScoreText(int nr)
+static char *getHallOfFameTimeText(int nr)
 {
-  if (!level.rate_time_over_score)
-    return int2str(scores.entry[nr].score, 5); // show normal score
-
-  if (level.use_step_counter)
-    return int2str(scores.entry[nr].time, 5);  // show number of steps
-
   static char score_text[10];
   int time_seconds = scores.entry[nr].time / FRAMES_PER_SECOND;
   int mm = (time_seconds / 60) % 60;
@@ -5772,11 +5795,141 @@ static char *getHallOfFameScoreText(int nr)
   return score_text;
 }
 
+static char *getHallOfFameScoreText(int nr)
+{
+  if (!level.rate_time_over_score)
+    return int2str(scores.entry[nr].score, 5); // show normal score
+  else if (level.use_step_counter)
+    return int2str(scores.entry[nr].time, 5);  // show number of steps
+  else
+    return getHallOfFameTimeText(nr);          // show playing time
+}
+
+static void HandleHallOfFame_SelectLevel(int step, int direction)
+{
+  int old_level_nr = scores.last_level_nr;
+  int new_level_nr = old_level_nr + step * direction;
+
+  if (new_level_nr < leveldir_current->first_level)
+    new_level_nr = leveldir_current->first_level;
+  if (new_level_nr > leveldir_current->last_level)
+    new_level_nr = leveldir_current->last_level;
+
+  if (setup.handicap && new_level_nr > leveldir_current->handicap_level)
+    new_level_nr = leveldir_current->handicap_level;
+
+  if (new_level_nr != old_level_nr)
+  {
+    PlaySound(SND_MENU_ITEM_SELECTING);
+
+    scores.last_level_nr = level_nr = new_level_nr;
+
+    LoadLocalAndServerScore(level_nr, TRUE);
+
+    DrawHallOfFame_setScoreEntries();
+
+    // force remapping optional gadgets (especially scroll bar)
+    UnmapScreenTreeGadgets();
+
+    // redraw complete high score screen, as sub-title has changed
+    ClearField();
+
+    // redraw level selection buttons (which have just been erased)
+    RedrawScreenMenuGadgets(SCREEN_MASK_SCORES);
+
+    HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, &score_entry_current);
+
+    SaveLevelSetup_SeriesInfo();
+  }
+}
+
 void HandleHallOfFame(int mx, int my, int dx, int dy, int button)
 {
   HandleChooseTree(mx, my, dx, dy, button, &score_entry_current);
 }
 
+static void DrawScoreInfo(int pos)
+{
+  struct ScoreEntry *entry = &scores.entry[pos];
+  int font_title = MENU_INFO_FONT_TITLE;
+  int font_head  = MENU_INFO_FONT_HEAD;
+  int font_text  = MENU_INFO_FONT_TEXT;
+  int font_foot  = MENU_INFO_FONT_FOOT;
+  int spacing_title = menu.headline1_spacing[GAME_MODE_SCOREINFO];
+  int spacing_para  = menu.paragraph_spacing[GAME_MODE_SCOREINFO];
+  int spacing_line  = menu.line_spacing[GAME_MODE_SCOREINFO];
+  int xstep = getFontWidth(font_text);
+  int ystep_title = getMenuTextStep(spacing_title, font_title);
+  int ystep_para  = getMenuTextStep(spacing_para,  font_text);
+  int ystep_line  = getMenuTextStep(spacing_line,  font_text);
+  int ystart  = mSY - SY + menu.top_spacing[GAME_MODE_SCOREINFO];
+  int ybottom = mSY - SY + SYSIZE - menu.bottom_spacing[GAME_MODE_SCOREINFO];
+  int xstart1 = mSX - SX + 2 * xstep;
+  int xstart2 = mSX - SX + 14 * xstep;
+
+  SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO);
+
+  UnmapAllGadgets();
+
+  FadeOut(REDRAW_FIELD);
+
+  ClearField();
+
+  drawChooseTreeHead(score_entries);
+  drawChooseTreeInfo(score_entries);
+
+  DrawTextSCentered(ystart, font_title, "Score Information:");
+  ystart += ystep_title;
+
+  DrawTextF(xstart1, ystart, font_head, "Level Set");
+  DrawTextF(xstart2, ystart, font_text, leveldir_current->name);
+  ystart += ystep_line;
+
+  DrawTextF(xstart1, ystart, font_head, "Level Name");
+  DrawTextF(xstart2, ystart, font_text, level.name);
+  ystart += ystep_para;
+
+  DrawTextF(xstart1, ystart, font_head, "Player");
+  DrawTextF(xstart2, ystart, font_text, entry->name);
+  ystart += ystep_line;
+
+  if (level.use_step_counter)
+  {
+    DrawTextF(xstart1, ystart, font_head, "Steps");
+    DrawTextF(xstart2, ystart, font_text, int2str(entry->time, 5));
+    ystart += ystep_line;
+  }
+  else
+  {
+    DrawTextF(xstart1, ystart, font_head, "Time");
+    DrawTextF(xstart2, ystart, font_text, getHallOfFameTimeText(pos));
+    ystart += ystep_line;
+  }
+
+  if (!level.rate_time_over_score || entry->score > 0)
+  {
+    DrawTextF(xstart1, ystart, font_head, "Score");
+    DrawTextF(xstart2, ystart, font_text, int2str(entry->score, 5));
+    ystart += ystep_line;
+  }
+
+  DrawTextSCentered(ybottom, font_foot, "Press any key or button to go back");
+
+  FadeIn(REDRAW_FIELD);
+}
+
+void HandleScoreInfo(int mx, int my, int dx, int dy, int button)
+{
+  if (button == MB_MENU_LEAVE || button == MB_MENU_CHOICE)
+  {
+    PlaySound(SND_MENU_ITEM_SELECTING);
+
+    SetGameStatus(GAME_MODE_SCORES);
+
+    DrawHallOfFame(level_nr);
+  }
+}
+
 
 // ============================================================================
 // setup screen functions
@@ -9608,6 +9761,22 @@ static struct
     GD_EVENT_PRESSED | GD_EVENT_REPEATED,
     FALSE, "next level"
   },
+  {
+    IMG_MENU_BUTTON_PREV_LEVEL2, IMG_MENU_BUTTON_PREV_LEVEL2_ACTIVE,
+    &menu.scores.button.prev_level, NULL,
+    SCREEN_CTRL_ID_PREV_LEVEL2,
+    SCREEN_MASK_SCORES,
+    GD_EVENT_PRESSED | GD_EVENT_REPEATED,
+    FALSE, "previous level"
+  },
+  {
+    IMG_MENU_BUTTON_NEXT_LEVEL2, IMG_MENU_BUTTON_NEXT_LEVEL2_ACTIVE,
+    &menu.scores.button.next_level, NULL,
+    SCREEN_CTRL_ID_NEXT_LEVEL2,
+    SCREEN_MASK_SCORES,
+    GD_EVENT_PRESSED | GD_EVENT_REPEATED,
+    FALSE, "next level"
+  },
   {
     IMG_MENU_BUTTON_FIRST_LEVEL, IMG_MENU_BUTTON_FIRST_LEVEL_ACTIVE,
     &menu.main.button.first_level, NULL,
@@ -9777,8 +9946,10 @@ static void CreateScreenMenubuttons(void)
   for (i = 0; i < NUM_SCREEN_MENUBUTTONS; i++)
   {
     struct MenuPosInfo *pos = menubutton_info[i].pos;
+    int screen_mask = menubutton_info[i].screen_mask;
     boolean is_touch_button = menubutton_info[i].is_touch_button;
     boolean is_check_button = menubutton_info[i].check_value != NULL;
+    boolean is_score_button = (screen_mask == SCREEN_MASK_SCORES);
     Bitmap *gd_bitmap_unpressed, *gd_bitmap_pressed;
     int gfx_unpressed, gfx_pressed;
     int x, y, width, height;
@@ -9826,6 +9997,21 @@ static void CreateScreenMenubuttons(void)
       checked = *menubutton_info[i].check_value;
     }
 
+    if (is_score_button)
+    {
+      // if x/y set to -1, dynamically place buttons next to title text
+      int title_width = getTextWidth(INFOTEXT_SCORE_ENTRY, FONT_TITLE_1);
+
+      if (pos->x == -1)
+       x = (id == SCREEN_CTRL_ID_PREV_LEVEL2 ?
+            SX + (SXSIZE - title_width) / 2 - width * 3 / 2 :
+            id == SCREEN_CTRL_ID_NEXT_LEVEL2 ?
+            SX + (SXSIZE + title_width) / 2 + width / 2 : 0);
+
+      if (pos->y == -1)
+       y = mSY + MENU_TITLE1_YPOS;
+    }
+
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
                      GDI_IMAGE_ID, gfx_unpressed,
@@ -10165,6 +10351,14 @@ static void HandleScreenGadgets(struct GadgetInfo *gi)
       HandleMainMenu_SelectLevel(step, +1, NO_DIRECT_LEVEL_SELECT);
       break;
 
+    case SCREEN_CTRL_ID_PREV_LEVEL2:
+      HandleHallOfFame_SelectLevel(step, -1);
+      break;
+
+    case SCREEN_CTRL_ID_NEXT_LEVEL2:
+      HandleHallOfFame_SelectLevel(step, +1);
+      break;
+
     case SCREEN_CTRL_ID_FIRST_LEVEL:
       HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT);
       break;