static void UpdateScreenMenuGadgets(int, boolean);
static void AdjustScoreInfoButtons_SelectScore(int, int, int);
-static void AdjustScoreInfoButtons_PlayTape(int, int);
+static void AdjustScoreInfoButtons_PlayTape(int, int, boolean);
static boolean OfferUploadTapes(void);
static void execOfferUploadTapes(void);
static char *getHallOfFameRankText(int, int);
static char *getHallOfFameScoreText(int, int);
+static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *);
+
static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS];
static int info_mode = INFO_MODE_MAIN;
// clear menu list area, but not title or scrollbar
DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32,
scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
+
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ ClearRectangle(drawto, mSX, mSY + MENU_SCREEN_START_YPOS * 32,
+ scrollbar_xpos - mSX, NUM_MENU_ENTRIES_ON_SCREEN * 32);
}
static void drawCursorExt(int xpos, int ypos, boolean active, int graphic)
return;
}
+ // needed if last screen was the playing screen, invoked from hall of fame
+ if (score_info_tape_play)
+ {
+ CloseDoor(DOOR_CLOSE_ALL);
+
+ SetGameStatus(GAME_MODE_SCOREINFO);
+
+ DrawScoreInfo(scores.last_entry_nr);
+
+ return;
+ }
+
// leveldir_current may be invalid (level group, parent link, node copy)
leveldir_current = getValidLevelSeries(leveldir_current, leveldir_last_valid);
info_info = info_info_main;
+ // use modified info screen info without info screen entries marked as hidden
+ info_info = getSetupInfoFinal(info_info);
+
// determine maximal number of info entries that can be displayed on screen
num_info_info = 0;
for (i = 0; info_info[i].type != 0 && i < NUM_MENU_ENTRIES_ON_SCREEN; i++)
return;
}
+#if defined(PLATFORM_ANDROID)
+ // touching the screen anywhere continues playing the next level
+ if ((mx || my) && scores.was_just_playing)
+ {
+ mx = my = 0;
+ button = MB_MENU_CHOICE;
+ }
+#endif
+
+ // any mouse click or direction input stops playing the next level
+ if ((mx || my || dx || dy) && scores.was_just_playing)
+ {
+ scores.was_just_playing = FALSE;
+ level_nr = scores.last_level_nr;
+ LoadLevel(level_nr);
+ }
+
if (mx || my) // mouse input
{
x = (mx - amSX) / 32;
}
else if (game_status == GAME_MODE_SCORES)
{
- if (game_status_last_screen == GAME_MODE_PLAYING &&
- setup.auto_play_next_level && setup.increment_levels &&
+ if (setup.auto_play_next_level && setup.increment_levels &&
scores.last_level_nr < leveldir_current->last_level &&
+ scores.was_just_playing &&
!network_playing)
{
StartGameActions(network.enabled, setup.autorecord,
level.random_seed);
return;
}
- else
+ else if (!scores.was_just_playing)
{
SetGameStatus(GAME_MODE_SCOREINFO);
void DrawHallOfFame(int level_nr)
{
scores.last_level_nr = level_nr;
+ scores.was_just_playing = (game_status_last_screen == GAME_MODE_PLAYING);
// (this is needed when called from GameEnd() after winning a game)
KeyboardAutoRepeatOn();
return getHallOfFameTimeText(nr); // show playing time
}
+static char *getHallOfFameTapeDateText(struct ScoreEntry *entry)
+{
+ static char tape_date[MAX_ISO_DATE_LEN + 1];
+ int i, j;
+
+ if (!strEqual(entry->tape_date, UNKNOWN_NAME) ||
+ strEqual(entry->tape_basename, UNDEFINED_FILENAME))
+ return entry->tape_date;
+
+ for (i = 0, j = 0; i < 8; i++, j++)
+ {
+ tape_date[j] = entry->tape_basename[i];
+
+ if (i == 3 || i == 5)
+ tape_date[++j] = '-';
+ }
+
+ tape_date[MAX_ISO_DATE_LEN] = '\0';
+
+ return tape_date;
+}
+
static void HandleHallOfFame_SelectLevel(int step, int direction)
{
int old_level_nr = scores.last_level_nr;
{
struct ScoreEntry *entry = &scores.entry[entry_nr];
char *pos_text = getHallOfFameRankText(entry_nr, 0);
+ char *tape_date = getHallOfFameTapeDateText(entry);
int font_title = MENU_INFO_FONT_TITLE;
int font_head = MENU_INFO_FONT_HEAD;
int font_text = MENU_INFO_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 xstart = mSX - SX + menu.left_spacing[GAME_MODE_SCOREINFO];
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 + 13 * xstep;
+ int xstart1 = xstart + xstep;
+ int xstart2 = xstart + xstep * 12;
int select_x = SX + xstart1;
int select_y1, select_y2;
int play_x, play_y;
int play_height = screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE]->height;
+ boolean play_visible = !strEqual(tape_date, UNKNOWN_NAME);
int font_width = getFontWidth(font_text);
int font_height = getFontHeight(font_text);
- int tape_date_width = getTextWidth(entry->tape_date, font_text);
+ int tape_date_width = getTextWidth(tape_date, font_text);
int pad_left = xstart2;
- int pad_right = MENU_SCREEN_INFO_SPACE_RIGHT;
+ int pad_right = menu.right_spacing[GAME_MODE_SCOREINFO];
int max_chars_per_line = (SXSIZE - pad_left - pad_right) / font_width;
int max_lines_per_text = 5;
int lines;
ClearField();
- // redraw score selection buttons (which have just been erased)
+ // redraw level selection buttons (which have just been erased)
RedrawScreenMenuGadgets(SCREEN_MASK_SCORES);
if (score_entries == NULL)
play_y = SY + ystart + (font_height - play_height) / 2;
DrawTextF(xstart1, ystart, font_head, "Tape Date");
- DrawTextF(xstart2, ystart, font_text, entry->tape_date);
+ DrawTextF(xstart2, ystart, font_text, tape_date);
ystart += ystep_line;
DrawTextF(xstart1, ystart, font_head, "Platform");
DrawTextSCentered(ybottom, font_foot, "Press any key or button to go back");
AdjustScoreInfoButtons_SelectScore(select_x, select_y1, select_y2);
- AdjustScoreInfoButtons_PlayTape(play_x, play_y);
+ AdjustScoreInfoButtons_PlayTape(play_x, play_y, play_visible);
}
static void DrawScoreInfo(int entry_nr)
{
scores.last_entry_nr = entry_nr;
-
- SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO);
+ score_info_tape_play = FALSE;
UnmapAllGadgets();
+ FreeScreenGadgets();
+ CreateScreenGadgets();
+
FadeOut(REDRAW_FIELD);
+ // needed if different viewport properties defined after playing score tape
+ ChangeViewportPropertiesIfNeeded();
+
+ // set this after "ChangeViewportPropertiesIfNeeded()" (which may reset it)
+ SetDrawDeactivationMask(REDRAW_NONE);
+ SetDrawBackgroundMask(REDRAW_FIELD);
+
+ // needed if different background image defined after playing score tape
+ SetMainBackgroundImage(IMG_BACKGROUND_SCORES);
+ SetMainBackgroundImageIfDefined(IMG_BACKGROUND_SCOREINFO);
+
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ ClearRectangle(gfx.background_bitmap, gfx.real_sx, gfx.real_sy + 64,
+ gfx.full_sxsize, gfx.full_sysize - 64);
+
DrawScoreInfo_Content(entry_nr);
// map gadgets for score info screen
static void HandleScoreInfo_PlayTape(void)
{
+ if (!PlayScoreTape(scores.last_entry_nr))
+ {
+ DrawScoreInfo_Content(scores.last_entry_nr);
+
+ FadeIn(REDRAW_FIELD);
+ }
}
void HandleScoreInfo(int mx, int my, int dx, int dy, int button)
SetGameStatus(GAME_MODE_SCORES);
- DrawHallOfFame(level_nr);
+ DrawHallOfFame(scores.last_level_nr);
}
else if (dx)
{
{ &setup.internal.menu_exit, execExitSetup },
{ &setup.internal.menu_save_and_exit, execSaveAndExitSetup },
+ { &setup.internal.info_title, execInfoTitleScreen },
+ { &setup.internal.info_elements, execInfoElements },
+ { &setup.internal.info_music, execInfoMusic },
+ { &setup.internal.info_credits, execInfoCredits },
+ { &setup.internal.info_program, execInfoProgram },
+ { &setup.internal.info_version, execInfoVersion },
+ { &setup.internal.info_levelset, execInfoLevelSet },
+ { &setup.internal.info_exit, execExitInfo },
+
{ NULL, NULL }
};
// if x/y set to -1, dynamically place buttons next to title text
int title_width = getTextWidth(INFOTEXT_SCORE_ENTRY, FONT_TITLE_1);
+ // special compatibility handling for "Snake Bite" graphics set
+ if (strPrefix(leveldir_current->identifier, "snake_bite"))
+ title_width = strlen(INFOTEXT_SCORE_ENTRY) * 32;
+
+ // use "SX" here to center buttons (ignore horizontal draw offset)
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);
+ // use "mSY" here to place buttons (respect vertical draw offset)
if (pos->y == -1)
y = (id == SCREEN_CTRL_ID_PREV_LEVEL2 ||
id == SCREEN_CTRL_ID_NEXT_LEVEL2 ? mSY + MENU_TITLE1_YPOS : 0);
ModifyGadget(gi_2, GDI_X, x, GDI_Y, y2, GDI_END);
}
-static void AdjustScoreInfoButtons_PlayTape(int x, int y)
+static void AdjustScoreInfoButtons_PlayTape(int x, int y, boolean visible)
{
struct GadgetInfo *gi = screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE];
struct MenuPosInfo *pos = menubutton_info[SCREEN_CTRL_ID_PLAY_TAPE].pos;
- if (pos->x == -1 && pos->y == -1)
- ModifyGadget(gi, GDI_X, x, GDI_Y, y, GDI_END);
+ // set gadget position dynamically, pre-defined or off-screen
+ int xx = (visible ? (pos->x == -1 ? x : pos->x) : POS_OFFSCREEN);
+ int yy = (visible ? (pos->y == -1 ? y : pos->y) : POS_OFFSCREEN);
+
+ ModifyGadget(gi, GDI_X, xx, GDI_Y, yy, GDI_END);
+ MapGadget(gi); // (needed if deactivated on last score page)
}
static void HandleScreenGadgets(struct GadgetInfo *gi)
}
}
+void HandleScreenGadgetKeys(Key key)
+{
+ if (key == setup.shortcut.tape_play)
+ HandleScreenGadgets(screen_gadget[SCREEN_CTRL_ID_PLAY_TAPE]);
+}
+
void DumpScreenIdentifiers(void)
{
int i;