X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fscreens.c;h=e68ec1a8d37efb07cee16488cc4a1c64f5a1a93f;hp=b22e82997d487ff03f6c566d311001053e2f1449;hb=7ecbe0a730dc19d8a46ffe6bbcb052f20d0c4152;hpb=2b8e172616210fa577b4ea3c4a777a3c09b40bb9 diff --git a/src/screens.c b/src/screens.c index b22e8299..e68ec1a8 100644 --- a/src/screens.c +++ b/src/screens.c @@ -60,20 +60,23 @@ /* sub-screens on the setup screen (specific) */ #define SETUP_MODE_CHOOSE_GAME_SPEED 16 #define SETUP_MODE_CHOOSE_SCROLL_DELAY 17 -#define SETUP_MODE_CHOOSE_SCREEN_MODE 18 -#define SETUP_MODE_CHOOSE_WINDOW_SIZE 19 -#define SETUP_MODE_CHOOSE_SCALING_TYPE 20 -#define SETUP_MODE_CHOOSE_GRAPHICS 21 -#define SETUP_MODE_CHOOSE_SOUNDS 22 -#define SETUP_MODE_CHOOSE_MUSIC 23 -#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE 24 -#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 25 -#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 26 -#define SETUP_MODE_CHOOSE_TOUCH_CONTROL 27 -#define SETUP_MODE_CHOOSE_MOVE_DISTANCE 28 -#define SETUP_MODE_CHOOSE_DROP_DISTANCE 29 - -#define MAX_SETUP_MODES 30 +#define SETUP_MODE_CHOOSE_SNAPSHOT_MODE 18 +#define SETUP_MODE_CHOOSE_SCREEN_MODE 19 +#define SETUP_MODE_CHOOSE_WINDOW_SIZE 20 +#define SETUP_MODE_CHOOSE_SCALING_TYPE 21 +#define SETUP_MODE_CHOOSE_GRAPHICS 22 +#define SETUP_MODE_CHOOSE_SOUNDS 23 +#define SETUP_MODE_CHOOSE_MUSIC 24 +#define SETUP_MODE_CHOOSE_VOLUME_SIMPLE 25 +#define SETUP_MODE_CHOOSE_VOLUME_LOOPS 26 +#define SETUP_MODE_CHOOSE_VOLUME_MUSIC 27 +#define SETUP_MODE_CHOOSE_TOUCH_CONTROL 28 +#define SETUP_MODE_CHOOSE_MOVE_DISTANCE 29 +#define SETUP_MODE_CHOOSE_DROP_DISTANCE 30 + +#define MAX_SETUP_MODES 31 + +#define MAX_MENU_MODES MAX(MAX_INFO_MODES, MAX_SETUP_MODES) /* for input setup functions */ #define SETUPINPUT_SCREEN_POS_START 0 @@ -97,9 +100,15 @@ MENU_SCREEN_INFO_YSTART2 - \ TILEY / 2) #define MAX_INFO_ELEMENTS_ON_SCREEN 128 -#define NUM_INFO_ELEMENTS_ON_SCREEN MIN(MENU_SCREEN_INFO_YSIZE / \ - MENU_SCREEN_INFO_YSTEP, \ - MAX_INFO_ELEMENTS_ON_SCREEN) +#define STD_INFO_ELEMENTS_ON_SCREEN (MENU_SCREEN_INFO_YSIZE / \ + MENU_SCREEN_INFO_YSTEP) +#define NUM_INFO_ELEMENTS_FROM_CONF \ + (menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] > 0 ? \ + menu.list_size_info[GFX_SPECIAL_ARG_INFO_ELEMENTS] : \ + MAX_MENU_ENTRIES_ON_SCREEN) +#define NUM_INFO_ELEMENTS_ON_SCREEN MIN(MIN(STD_INFO_ELEMENTS_ON_SCREEN, \ + MAX_INFO_ELEMENTS_ON_SCREEN), \ + NUM_INFO_ELEMENTS_FROM_CONF) #define MAX_MENU_ENTRIES_ON_SCREEN (SCR_FIELDY - MENU_SCREEN_START_YPOS) #define MAX_MENU_TEXT_LENGTH_BIG 13 #define MAX_MENU_TEXT_LENGTH_MEDIUM (MAX_MENU_TEXT_LENGTH_BIG * 2) @@ -165,10 +174,8 @@ static void HandleChooseTree(int, int, int, int, int, TreeInfo **); static void DrawChooseLevelSet(void); static void DrawChooseLevelNr(void); static void DrawInfoScreen(void); -static void DrawAndFadeInInfoScreen(int); static void DrawSetupScreen(void); -static void DrawInfoScreenExt(int, int); static void DrawInfoScreen_NotAvailable(char *, char *); static void DrawInfoScreen_HelpAnim(int, int, boolean); static void DrawInfoScreen_HelpText(int, int, int, int); @@ -201,6 +208,9 @@ static TreeInfo *scaling_type_current = NULL; static TreeInfo *scroll_delays = NULL; static TreeInfo *scroll_delay_current = NULL; +static TreeInfo *snapshot_modes = NULL; +static TreeInfo *snapshot_mode_current = NULL; + static TreeInfo *game_speeds = NULL; static TreeInfo *game_speed_current = NULL; @@ -310,6 +320,19 @@ static struct { -1, NULL }, }; +static struct +{ + char *value; + char *text; +} snapshot_modes_list[] = +{ + { STR_SNAPSHOT_MODE_OFF, "Off" }, + { STR_SNAPSHOT_MODE_EVERY_STEP, "Every Step" }, + { STR_SNAPSHOT_MODE_EVERY_MOVE, "Every Move" }, + + { NULL, NULL }, +}; + static struct { int value; @@ -317,6 +340,9 @@ static struct } volumes_list[] = { { 0, "0 %" }, + { 1, "1 %" }, + { 2, "2 %" }, + { 5, "5 %" }, { 10, "10 %" }, { 20, "20 %" }, { 30, "30 %" }, @@ -411,12 +437,18 @@ static struct menu.list_size[game_status] : \ MAX_MENU_ENTRIES_ON_SCREEN) +#define IN_VIS_MENU(x, y) IN_FIELD(x, y, SCR_FIELDX, \ + NUM_MENU_ENTRIES_ON_SCREEN) + /* title display and control definitions */ #define MAX_NUM_TITLE_SCREENS (2 * MAX_NUM_TITLE_IMAGES + \ 2 * MAX_NUM_TITLE_MESSAGES) +#define NO_DIRECT_LEVEL_SELECT (-1) + + static int num_title_screens = 0; struct TitleControlInfo @@ -478,9 +510,6 @@ static char *main_text_level_year = NULL; static char *main_text_level_imported_from = NULL; static char *main_text_level_imported_by = NULL; static char *main_text_level_tested_by = NULL; -static char *main_text_title_1 = PROGRAM_TITLE_STRING; -static char *main_text_title_2 = PROGRAM_COPYRIGHT_STRING; -static char *main_text_title_3 = PROGRAM_GAME_BY_STRING; struct MainControlInfo { @@ -630,19 +659,19 @@ static struct MainControlInfo main_controls[] = { MAIN_CONTROL_TITLE_1, NULL, -1, - &menu.main.text.title_1, &main_text_title_1, + &menu.main.text.title_1, &setup.internal.program_title, NULL, NULL, }, { MAIN_CONTROL_TITLE_2, NULL, -1, - &menu.main.text.title_2, &main_text_title_2, + &menu.main.text.title_2, &setup.internal.program_copyright, NULL, NULL, }, { MAIN_CONTROL_TITLE_3, NULL, -1, - &menu.main.text.title_3, &main_text_title_3, + &menu.main.text.title_3, &setup.internal.program_company, NULL, NULL, }, @@ -955,10 +984,8 @@ static void InitializeMainControls() if (pos_button != NULL) /* (x/y may be -1/-1 here) */ { - if (pos_button->width == 0) - pos_button->width = button_width; - if (pos_button->height == 0) - pos_button->height = button_height; + pos_button->width = button_width; + pos_button->height = button_height; } if (pos_text != NULL) /* (x/y may be -1/-1 here) */ @@ -966,18 +993,19 @@ static void InitializeMainControls() /* calculate size for non-clickable text -- needed for text alignment */ boolean calculate_text_size = (pos_button == NULL && text != NULL); + if (pos_text->width == -1 || calculate_text_size) + pos_text->width = text_width; + if (pos_text->height == -1 || calculate_text_size) + pos_text->height = text_height; + if (visibleMenuPos(pos_button)) { if (pos_text->x == -1) pos_text->x = pos_button->x + pos_button->width; if (pos_text->y == -1) - pos_text->y = pos_button->y; + pos_text->y = + pos_button->y + (pos_button->height - pos_text->height) / 2; } - - if (pos_text->width == -1 || calculate_text_size) - pos_text->width = text_width; - if (pos_text->height == -1 || calculate_text_size) - pos_text->height = text_height; } if (pos_input != NULL) /* (x/y may be -1/-1 here) */ @@ -998,8 +1026,24 @@ static void InitializeMainControls() } } +static void DrawPressedGraphicThruMask(int dst_x, int dst_y, + int graphic, boolean pressed) +{ + struct GraphicInfo *g = &graphic_info[graphic]; + Bitmap *src_bitmap; + int src_x, src_y; + int xoffset = (pressed ? g->pressed_xoffset : 0); + int yoffset = (pressed ? g->pressed_yoffset : 0); + + getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + + BlitBitmapMasked(src_bitmap, drawto, src_x + xoffset, src_y + yoffset, + g->width, g->height, dst_x, dst_y); +} + static void DrawCursorAndText_Main_Ext(int nr, boolean active_text, - boolean active_input) + boolean active_input, + boolean pressed_button) { int i; @@ -1036,7 +1080,7 @@ static void DrawCursorAndText_Main_Ext(int nr, boolean active_text, int y = mSY + pos->y; DrawBackgroundForGraphic(x, y, pos->width, pos->height, button_graphic); - DrawFixedGraphicThruMaskExt(drawto, x, y, button_graphic, 0); + DrawPressedGraphicThruMask(x, y, button_graphic, pressed_button); } if (visibleTextPos(pos_text) && text != NULL) @@ -1068,15 +1112,17 @@ static void DrawCursorAndText_Main_Ext(int nr, boolean active_text, } } -static void DrawCursorAndText_Main(int nr, boolean active_text) +static void DrawCursorAndText_Main(int nr, boolean active_text, + boolean pressed_button) { - DrawCursorAndText_Main_Ext(nr, active_text, FALSE); + DrawCursorAndText_Main_Ext(nr, active_text, FALSE, pressed_button); } #if 0 -static void DrawCursorAndText_Main_Input(int nr, boolean active_text) +static void DrawCursorAndText_Main_Input(int nr, boolean active_text, + boolean pressed_button) { - DrawCursorAndText_Main_Ext(nr, active_text, TRUE); + DrawCursorAndText_Main_Ext(nr, active_text, TRUE, pressed_button); } #endif @@ -1122,6 +1168,38 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y) y >= rect_y && y < rect_y + rect->height); } +static void AdjustScrollbar(int id, int items_max, int items_visible, + int item_position) +{ + struct GadgetInfo *gi = screen_gadget[id]; + + if (item_position > items_max - items_visible) + item_position = items_max - items_visible; + + ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max, + GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible, + GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END); +} + +static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti) +{ + AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN, + first_entry); +} + +static void clearMenuListArea() +{ + int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset; + + /* correct scrollbar position if placed outside menu (playfield) area */ + if (scrollbar_xpos > SX + SC_SCROLLBAR_XPOS) + scrollbar_xpos = SX + SC_SCROLLBAR_XPOS; + + /* 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); +} + static void drawCursorExt(int xpos, int ypos, boolean active, int graphic) { static int cursor_array[MAX_LEV_FIELDY]; @@ -1169,16 +1247,9 @@ static void drawChooseTreeCursor(int ypos, boolean active) void DrawHeadline() { - DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, PROGRAM_TITLE_STRING); - DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, PROGRAM_COPYRIGHT_STRING); -} - -int effectiveGameStatus() -{ - if (game_status == GAME_MODE_INFO && info_mode == INFO_MODE_TITLE) - return GAME_MODE_TITLE; - - return game_status; + DrawTextSCentered(MENU_TITLE1_YPOS, FONT_TITLE_1, getProgramTitleString()); + DrawTextSCentered(MENU_TITLE2_YPOS, FONT_TITLE_2, + setup.internal.program_copyright); } void DrawTitleScreenImage(int nr, boolean initial) @@ -1218,10 +1289,7 @@ void DrawTitleScreenImage(int nr, boolean initial) ClearRectangleOnBackground(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE); if (DrawingOnBackground(dst_x, dst_y)) - { - SetClipOrigin(bitmap, bitmap->stored_clip_gc, dst_x - src_x, dst_y - src_y); BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y); - } else BlitBitmap(bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y); @@ -1290,10 +1358,11 @@ boolean CheckTitleScreen(boolean levelset_has_changed) return (show_titlescreen && num_title_screens > 0); } -void DrawMainMenuExt(int fade_mask, boolean do_fading) +void DrawMainMenu() { static LevelDirTree *leveldir_last_valid = NULL; boolean levelset_has_changed = FALSE; + int fade_mask = REDRAW_FIELD; LimitScreenUpdates(FALSE); @@ -1307,9 +1376,6 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) KeyboardAutoRepeatOn(); ActivateJoystick(); - SetDrawDeactivationMask(REDRAW_NONE); - SetDrawBackgroundMask(REDRAW_FIELD); - audio.sound_deactivated = FALSE; GetPlayerConfig(); @@ -1342,13 +1408,16 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) /* needed if last screen (level choice) changed graphics, sounds or music */ ReloadCustomArtwork(0); + /* needed if different viewport properties defined for menues */ + ChangeViewportPropertiesIfNeeded(); + if (redraw_mask & REDRAW_ALL) fade_mask = REDRAW_ALL; - FadeOut(fade_mask); + if (CheckIfGlobalBorderHasChanged()) + fade_mask = REDRAW_ALL; - /* needed if different viewport properties defined for menues */ - ChangeViewportPropertiesIfNeeded(); + FadeOut(fade_mask); /* needed if last screen was the editor screen */ UndrawSpecialEditorDoor(); @@ -1357,6 +1426,7 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) if (CheckTitleScreen(levelset_has_changed)) { + game_status_last_screen = GAME_MODE_MAIN; game_status = GAME_MODE_TITLE; DrawTitleScreen(); @@ -1371,16 +1441,22 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) LoadLevel(level_nr); LoadScore(level_nr); + // set this after "ChangeViewportPropertiesIfNeeded()" (which may reset it) + SetDrawDeactivationMask(REDRAW_NONE); + SetDrawBackgroundMask(REDRAW_FIELD); + SetMainBackgroundImage(IMG_BACKGROUND_MAIN); +#if 0 if (fade_mask == REDRAW_ALL) - RedrawBackground(); + RedrawGlobalBorder(); +#endif ClearField(); InitializeMainControls(); - DrawCursorAndText_Main(-1, FALSE); + DrawCursorAndText_Main(-1, FALSE, FALSE); DrawPreviewLevelInitial(); HandleMainMenu(0, 0, 0, 0, MB_MENU_INITIALIZE); @@ -1402,11 +1478,12 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) MapScreenMenuGadgets(SCREEN_MASK_MAIN); /* copy actual game door content to door double buffer for OpenDoor() */ + BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0); BlitBitmap(drawto, bitmap_db_door_2, VX, VY, VXSIZE, VYSIZE, 0, 0); OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); - DrawMaskedBorder(REDRAW_ALL); + DrawMaskedBorder(fade_mask); FadeIn(fade_mask); FadeSetEnterMenu(); @@ -1422,21 +1499,11 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2); } -void DrawAndFadeInMainMenu(int fade_mask) -{ - DrawMainMenuExt(fade_mask, TRUE); -} - -void DrawMainMenu() -{ - DrawMainMenuExt(REDRAW_ALL, FALSE); -} - -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) static void gotoTopLevelDir() { - /* move upwards to top level directory */ - while (leveldir_current->node_parent) + /* move upwards until inside (but not above) top level directory */ + while (leveldir_current->node_parent && + !strEqual(leveldir_current->node_parent->subdir, STRING_TOP_DIRECTORY)) { /* write a "path" into level tree for easy navigation to last level */ if (leveldir_current->node_parent->node_group->cl_first == -1) @@ -1461,7 +1528,6 @@ static void gotoTopLevelDir() leveldir_current = leveldir_current->node_parent; } } -#endif void HandleTitleScreen(int mx, int my, int dx, int dy, int button) { @@ -1469,7 +1535,6 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) static int title_screen_nr = 0; static int last_sound = -1, last_music = -1; boolean return_to_main_menu = FALSE; - boolean use_fading_main_menu = TRUE; struct TitleControlInfo *tci; struct TitleFadingInfo fading_default; struct TitleFadingInfo fading_last = fading; @@ -1485,7 +1550,7 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) last_sound = SND_UNDEFINED; last_music = MUS_UNDEFINED; - if (game_status == GAME_MODE_INFO) + if (game_status_last_screen == GAME_MODE_INFO) { if (num_title_screens == 0) { @@ -1498,8 +1563,13 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) FadeSoundsAndMusic(); FadeOut(REDRAW_ALL); + + /* only required to update logic for redrawing global border */ + ClearField(); } + ChangeViewportPropertiesIfNeeded(); + if (tci->is_image) DrawTitleScreenImage(tci->local_nr, tci->initial); else @@ -1544,16 +1614,17 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) if (button == MB_MENU_LEAVE) { return_to_main_menu = TRUE; - use_fading_main_menu = FALSE; } else if (button == MB_MENU_CHOICE) { - if (game_status == GAME_MODE_INFO && num_title_screens == 0) + if (game_status_last_screen == GAME_MODE_INFO && num_title_screens == 0) { FadeSetEnterScreen(); + game_status = GAME_MODE_INFO; info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + + DrawInfoScreen(); return; } @@ -1614,27 +1685,35 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) { SetMouseCursor(CURSOR_DEFAULT); - if (game_status == GAME_MODE_INFO) + /* force full menu screen redraw after displaying title screens */ + redraw_mask = REDRAW_ALL; + + if (game_status_last_screen == GAME_MODE_INFO) { + game_status = GAME_MODE_INFO; info_mode = INFO_MODE_MAIN; - DrawInfoScreenExt(REDRAW_ALL, use_fading_main_menu); + DrawInfoScreen(); } else /* default: return to main menu */ { game_status = GAME_MODE_MAIN; - DrawMainMenuExt(REDRAW_ALL, use_fading_main_menu); + DrawMainMenu(); } } } -void HandleMainMenu_SelectLevel(int step, int direction) +void HandleMainMenu_SelectLevel(int step, int direction, int selected_level_nr) { int old_level_nr = level_nr; int new_level_nr; - new_level_nr = old_level_nr + step * direction; + if (selected_level_nr != NO_DIRECT_LEVEL_SELECT) + new_level_nr = selected_level_nr; + else + 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) @@ -1643,7 +1722,7 @@ void HandleMainMenu_SelectLevel(int step, int direction) if (setup.handicap && new_level_nr > leveldir_current->handicap_level) { /* skipping levels is only allowed when trying to skip single level */ - if (setup.skip_levels && step == 1 && + if (setup.skip_levels && new_level_nr == old_level_nr + 1 && Request("Level still unsolved! Skip despite handicap?", REQ_ASK)) { leveldir_current->handicap_level++; @@ -1674,19 +1753,21 @@ void HandleMainMenu_SelectLevel(int step, int direction) /* needed because DrawPreviewLevelInitial() takes some time */ BackToFront(); - SyncDisplay(); + /* SyncDisplay(); */ } } void HandleMainMenu(int mx, int my, int dx, int dy, int button) { static int choice = MAIN_CONTROL_GAME; + static boolean button_pressed_last = FALSE; + boolean button_pressed = FALSE; int pos = choice; int i; if (button == MB_MENU_INITIALIZE) { - DrawCursorAndText_Main(choice, TRUE); + DrawCursorAndText_Main(choice, TRUE, FALSE); return; } @@ -1706,6 +1787,23 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) break; } } + + // handle pressed/unpressed state for active/inactive menu buttons + // (if pos != -1, "i" contains index position corresponding to "pos") + if (button && + pos >= MAIN_CONTROL_NAME && pos <= MAIN_CONTROL_QUIT && + insideMenuPosRect(main_controls[i].pos_button, mx - mSX, my - mSY)) + button_pressed = TRUE; + + if (button_pressed != button_pressed_last) + { + DrawCursorAndText_Main(choice, TRUE, button_pressed); + + if (button_pressed) + PlaySound(SND_MENU_BUTTON_PRESSING); + else + PlaySound(SND_MENU_BUTTON_RELEASING); + } } else if (dx || dy) /* keyboard input */ { @@ -1718,18 +1816,22 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) if (pos == MAIN_CONTROL_LEVELS && dx != 0 && button) { - HandleMainMenu_SelectLevel(1, dx < 0 ? -1 : +1); + HandleMainMenu_SelectLevel(1, (dx < 0 ? -1 : +1), NO_DIRECT_LEVEL_SELECT); } else if (pos == MAIN_CONTROL_FIRST_LEVEL && !button) { - HandleMainMenu_SelectLevel(MAX_LEVELS, -1); + HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT); } else if (pos == MAIN_CONTROL_LAST_LEVEL && !button) { - HandleMainMenu_SelectLevel(MAX_LEVELS, +1); + HandleMainMenu_SelectLevel(MAX_LEVELS, +1, NO_DIRECT_LEVEL_SELECT); } else if (pos == MAIN_CONTROL_LEVEL_NUMBER && !button) { + StopAnimation(); + + CloseDoor(DOOR_CLOSE_2); + game_status = GAME_MODE_LEVELNR; ChangeViewportPropertiesIfNeeded(); @@ -1744,8 +1846,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) { PlaySound(SND_MENU_ITEM_ACTIVATING); - DrawCursorAndText_Main(choice, FALSE); - DrawCursorAndText_Main(pos, TRUE); + DrawCursorAndText_Main(choice, FALSE, FALSE); + DrawCursorAndText_Main(pos, TRUE, button_pressed); choice = pos; } @@ -1764,14 +1866,17 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) { if (leveldir_first) { + StopAnimation(); + + CloseDoor(DOOR_CLOSE_2); + game_status = GAME_MODE_LEVELS; SaveLevelSetup_LastSeries(); SaveLevelSetup_SeriesInfo(); -#if defined(CREATE_SPECIAL_EDITION_RND_JUE) - gotoTopLevelDir(); -#endif + if (setup.internal.choose_from_top_leveldir) + gotoTopLevelDir(); ChangeViewportPropertiesIfNeeded(); @@ -1780,9 +1885,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_SCORES) { - game_status = GAME_MODE_SCORES; + StopAnimation(); - ChangeViewportPropertiesIfNeeded(); + CloseDoor(DOOR_CLOSE_2); + + game_status = GAME_MODE_SCORES; DrawHallOfFame(-1); } @@ -1792,6 +1899,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) !strEqual(setup.player_name, "Artsoft")) Request("This level is read only!", REQ_CONFIRM); + StopAnimation(); + CloseDoor(DOOR_CLOSE_2); game_status = GAME_MODE_EDITOR; @@ -1802,6 +1911,10 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_INFO) { + StopAnimation(); + + CloseDoor(DOOR_CLOSE_2); + game_status = GAME_MODE_INFO; info_mode = INFO_MODE_MAIN; @@ -1811,10 +1924,16 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_GAME) { + StopAnimation(); + StartGameActions(options.network, setup.autorecord, level.random_seed); } else if (pos == MAIN_CONTROL_SETUP) { + StopAnimation(); + + CloseDoor(DOOR_CLOSE_2); + game_status = GAME_MODE_SETUP; setup_mode = SETUP_MODE_MAIN; @@ -1832,6 +1951,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } } } + + button_pressed_last = button_pressed; } @@ -1840,7 +1961,8 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) /* ========================================================================= */ static struct TokenInfo *info_info; -static int num_info_info; +static int num_info_info; /* number of info entries shown on screen */ +static int max_info_info; /* total number of info entries in list */ static void execInfoTitleScreen() { @@ -1895,7 +2017,7 @@ static void execExitInfo() { game_status = GAME_MODE_MAIN; - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } static struct TokenInfo info_info_main[] = @@ -1913,26 +2035,122 @@ static struct TokenInfo info_info_main[] = { 0, NULL, NULL } }; -static void DrawCursorAndText_Info(int pos, boolean active) +static int getMenuTextFont(int type) +{ + if (type & (TYPE_SWITCH | + TYPE_YES_NO | + TYPE_YES_NO_AUTO | + TYPE_STRING | + TYPE_ECS_AGA | + TYPE_KEYTEXT | + TYPE_ENTER_LIST)) + return FONT_MENU_2; + else + return FONT_MENU_1; +} + +static struct TokenInfo *setup_info; +static struct TokenInfo setup_info_input[]; + +static struct TokenInfo *menu_info; + +static void DrawCursorAndText_Menu_Ext(struct TokenInfo *token_info, + int screen_pos, int menu_info_pos_raw, + boolean active) { + int pos = (menu_info_pos_raw < 0 ? screen_pos : menu_info_pos_raw); + struct TokenInfo *ti = &token_info[pos]; int xpos = MENU_SCREEN_START_XPOS; - int ypos = MENU_SCREEN_START_YPOS + pos; - int font_nr = FONT_MENU_1; + int ypos = MENU_SCREEN_START_YPOS + screen_pos; + int font_nr = getMenuTextFont(ti->type); + + if (token_info == setup_info_input) + font_nr = FONT_MENU_1; if (active) font_nr = FONT_ACTIVE(font_nr); - DrawText(mSX + xpos * 32, mSY + ypos * 32, info_info[pos].text, font_nr); + DrawText(mSX + xpos * 32, mSY + ypos * 32, ti->text, font_nr); + + if (ti->type & ~TYPE_SKIP_ENTRY) + drawCursor(screen_pos, active); +} + +static void DrawCursorAndText_Menu(int screen_pos, int menu_info_pos_raw, + boolean active) +{ + DrawCursorAndText_Menu_Ext(menu_info, screen_pos, menu_info_pos_raw, active); +} + +static void DrawCursorAndText_Setup(int screen_pos, int menu_info_pos_raw, + boolean active) +{ + DrawCursorAndText_Menu_Ext(setup_info, screen_pos, menu_info_pos_raw, active); +} + +static char *screen_mode_text; +static char *window_size_text; +static char *scaling_type_text; + +static void drawSetupValue(int, int); + +static void drawMenuInfoList(int first_entry, int num_page_entries, + int max_page_entries) +{ + int i; + + if (first_entry + num_page_entries > max_page_entries) + first_entry = 0; + + clearMenuListArea(); + + for (i = 0; i < num_page_entries; i++) + { + int menu_info_pos = first_entry + i; + struct TokenInfo *si = &menu_info[menu_info_pos]; + void *value_ptr = si->value; + + /* set some entries to "unchangeable" according to other variables */ + if ((value_ptr == &setup.sound_simple && !audio.sound_available) || + (value_ptr == &setup.sound_loops && !audio.loops_available) || + (value_ptr == &setup.sound_music && !audio.music_available) || + (value_ptr == &setup.fullscreen && !video.fullscreen_available) || + (value_ptr == &screen_mode_text && !video.fullscreen_available) || + (value_ptr == &window_size_text && !video.window_scaling_available) || + (value_ptr == &scaling_type_text && !video.window_scaling_available)) + si->type |= TYPE_GHOSTED; + + if (si->type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST)) + initCursor(i, IMG_MENU_BUTTON_ENTER_MENU); + else if (si->type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) + initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); + else if (si->type & ~TYPE_SKIP_ENTRY) + initCursor(i, IMG_MENU_BUTTON); - if (info_info[pos].type & ~TYPE_SKIP_ENTRY) - drawCursor(pos, active); + DrawCursorAndText_Menu(i, menu_info_pos, FALSE); + + if (si->type & TYPE_VALUE && + menu_info == setup_info) + drawSetupValue(i, menu_info_pos); + } } -static void DrawInfoScreen_Main(int fade_mask, boolean do_fading) +static void DrawInfoScreen_Main() { + int fade_mask = REDRAW_FIELD; int i; + if (redraw_mask & REDRAW_ALL) + fade_mask = REDRAW_ALL; + + if (CheckIfGlobalBorderHasChanged()) + fade_mask = REDRAW_ALL; + UnmapAllGadgets(); + + FreeScreenGadgets(); + CreateScreenGadgets(); + CloseDoor(DOOR_CLOSE_2); /* (needed after displaying title screens which disable auto repeat) */ @@ -1942,36 +2160,30 @@ static void DrawInfoScreen_Main(int fade_mask, boolean do_fading) FadeOut(fade_mask); - if (fade_mask == REDRAW_ALL) - { - RedrawBackground(); + ChangeViewportPropertiesIfNeeded(); - OpenDoor(DOOR_CLOSE_1 | DOOR_CLOSE_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); - } + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); ClearField(); DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen"); info_info = info_info_main; - num_info_info = 0; - - for (i = 0; info_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++) - { - if (info_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST)) - initCursor(i, IMG_MENU_BUTTON_ENTER_MENU); - else if (info_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) - initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); - else if (info_info[i].type & ~TYPE_SKIP_ENTRY) - initCursor(i, IMG_MENU_BUTTON); - - DrawCursorAndText_Info(i, FALSE); + // 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++) num_info_info++; - } + + // determine maximal number of info entries available for menu of info screen + max_info_info = 0; + for (i = 0; info_info[i].type != 0; i++) + max_info_info++; HandleInfoScreen_Main(0, 0, 0, 0, MB_MENU_INITIALIZE); + MapScreenGadgets(max_info_info); + PlayMenuSound(); PlayMenuMusic(); @@ -1982,38 +2194,90 @@ static void DrawInfoScreen_Main(int fade_mask, boolean do_fading) InitAnimation(); } -void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button) +static void changeSetupValue(int, int, int); + +void HandleMenuScreen(int mx, int my, int dx, int dy, int button, + int mode, int num_page_entries, int max_page_entries) { - static int choice_store[MAX_INFO_MODES]; - int choice = choice_store[info_mode]; /* always starts with 0 */ + static int num_page_entries_all_last[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES]; + static int choice_stores[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES]; + static int first_entry_stores[NUM_SPECIAL_GFX_ARGS][MAX_MENU_MODES]; + int *num_page_entries_last = num_page_entries_all_last[game_status]; + int *choice_store = choice_stores[game_status]; + int *first_entry_store = first_entry_stores[game_status]; + int choice = choice_store[mode]; /* starts with 0 */ + int first_entry = first_entry_store[mode]; /* starts with 0 */ int x = 0; - int y = choice; + int y = choice - first_entry; + int y_old = y; + boolean position_set_by_scrollbar = (dx == 999); + int step = (button == 1 ? 1 : button == 2 ? 5 : 10); + int i; if (button == MB_MENU_INITIALIZE) { + // check if number of menu page entries has changed (may happen by change + // of custom artwork definition value for 'list_size' for this menu screen) + // (in this case, the last menu position most probably has to be corrected) + if (num_page_entries != num_page_entries_last[mode]) + { + choice_store[mode] = first_entry_store[mode] = 0; + + choice = first_entry = 0; + y = y_old = 0; + + num_page_entries_last[mode] = num_page_entries; + } + /* advance to first valid menu entry */ - while (choice < num_info_info && - info_info[choice].type & TYPE_SKIP_ENTRY) + while (choice < num_page_entries && + menu_info[choice].type & TYPE_SKIP_ENTRY) choice++; - choice_store[info_mode] = choice; - DrawCursorAndText_Info(choice, TRUE); + if (position_set_by_scrollbar) + first_entry = first_entry_store[mode] = dy; + else + AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries, + NUM_MENU_ENTRIES_ON_SCREEN, first_entry); + + drawMenuInfoList(first_entry, num_page_entries, max_page_entries); + + if (choice < first_entry) + { + choice = first_entry; + + if (menu_info[choice].type & TYPE_SKIP_ENTRY) + choice++; + } + else if (choice > first_entry + num_page_entries - 1) + { + choice = first_entry + num_page_entries - 1; + + if (menu_info[choice].type & TYPE_SKIP_ENTRY) + choice--; + } + + choice_store[mode] = choice; + + DrawCursorAndText_Menu(choice - first_entry, choice, TRUE); return; } else if (button == MB_MENU_LEAVE) { - for (y = 0; y < num_info_info; y++) + PlaySound(SND_MENU_ITEM_SELECTING); + + for (i = 0; i < max_page_entries; i++) { - if (info_info[y].type & TYPE_LEAVE_MENU) + if (menu_info[i].type & TYPE_LEAVE_MENU) { - void (*menu_callback_function)(void) = info_info[y].value; + void (*menu_callback_function)(void) = menu_info[i].value; FadeSetLeaveMenu(); menu_callback_function(); - break; /* absolutely needed because function changes 'info_info'! */ + break; /* absolutely needed because function changes 'menu_info'! */ } } @@ -2025,65 +2289,202 @@ void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button) x = (mx - mSX) / 32; y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS; } - else if (dx || dy) /* keyboard input */ + else if (dx || dy) /* keyboard or scrollbar/scrollbutton input */ { - if (dx) - { - int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER); + /* move cursor instead of scrolling when already at start/end of list */ + if (dy == -1 * SCROLL_LINE && first_entry == 0) + dy = -1; + else if (dy == +1 * SCROLL_LINE && + first_entry + num_page_entries == max_page_entries) + dy = 1; - if (info_info[choice].type & menu_navigation_type || - info_info[choice].type & TYPE_ENTER_SCREEN || - info_info[choice].type & TYPE_BOOLEAN_STYLE || - info_info[choice].type & TYPE_YES_NO_AUTO) - button = MB_MENU_CHOICE; - } - else if (dy) - y = choice + dy; + /* handle scrolling screen one line or page */ + if (y + dy < 0 || + y + dy > num_page_entries - 1) + { + boolean redraw = FALSE; + + if (ABS(dy) == SCROLL_PAGE) + step = num_page_entries - 1; + + if (dy < 0 && first_entry > 0) + { + /* scroll page/line up */ + + first_entry -= step; + if (first_entry < 0) + first_entry = 0; + + redraw = TRUE; + } + else if (dy > 0 && first_entry + num_page_entries < max_page_entries) + { + /* scroll page/line down */ + + first_entry += step; + if (first_entry + num_page_entries > max_page_entries) + first_entry = MAX(0, max_page_entries - num_page_entries); + + redraw = TRUE; + } + + if (redraw) + { + choice += first_entry - first_entry_store[mode]; + + if (choice < first_entry) + { + choice = first_entry; + + if (menu_info[choice].type & TYPE_SKIP_ENTRY) + choice++; + } + else if (choice > first_entry + num_page_entries - 1) + { + choice = first_entry + num_page_entries - 1; + + if (menu_info[choice].type & TYPE_SKIP_ENTRY) + choice--; + } + else if (menu_info[choice].type & TYPE_SKIP_ENTRY) + { + choice += SIGN(dy); + + if (choice < first_entry || + choice > first_entry + num_page_entries - 1) + first_entry += SIGN(dy); + } + + first_entry_store[mode] = first_entry; + choice_store[mode] = choice; + + drawMenuInfoList(first_entry, num_page_entries, max_page_entries); + + DrawCursorAndText_Menu(choice - first_entry, choice, TRUE); + + AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries, + NUM_MENU_ENTRIES_ON_SCREEN, first_entry); + } + + return; + } + + if (dx) + { + int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER); + + if (menu_info[choice].type & menu_navigation_type || + menu_info[choice].type & TYPE_BOOLEAN_STYLE || + menu_info[choice].type & TYPE_YES_NO_AUTO) + button = MB_MENU_CHOICE; + } + else if (dy) + y += dy; /* jump to next non-empty menu entry (up or down) */ - while (y > 0 && y < num_info_info - 1 && - info_info[y].type & TYPE_SKIP_ENTRY) + while (first_entry + y > 0 && + first_entry + y < max_page_entries - 1 && + menu_info[first_entry + y].type & TYPE_SKIP_ENTRY) y += dy; + + if (!IN_VIS_MENU(x, y)) + { + choice += y - y_old; + + if (choice < first_entry) + first_entry = choice; + else if (choice > first_entry + num_page_entries - 1) + first_entry = choice - num_page_entries + 1; + + if (first_entry >= 0 && + first_entry + num_page_entries <= max_page_entries) + { + first_entry_store[mode] = first_entry; + + if (choice < first_entry) + choice = first_entry; + else if (choice > first_entry + num_page_entries - 1) + choice = first_entry + num_page_entries - 1; + + choice_store[mode] = choice; + + drawMenuInfoList(first_entry, num_page_entries, max_page_entries); + + DrawCursorAndText_Menu(choice - first_entry, choice, TRUE); + + AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_page_entries, + NUM_MENU_ENTRIES_ON_SCREEN, first_entry); + } + + return; + } } - if (IN_VIS_FIELD(x, y) && - y >= 0 && y < num_info_info && info_info[y].type & ~TYPE_SKIP_ENTRY) + if (!anyScrollbarGadgetActive() && + IN_VIS_MENU(x, y) && + mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x && + y >= 0 && y < num_page_entries) { if (button) { - if (y != choice) + if (first_entry + y != choice && + menu_info[first_entry + y].type & ~TYPE_SKIP_ENTRY) { PlaySound(SND_MENU_ITEM_ACTIVATING); - DrawCursorAndText_Info(choice, FALSE); - DrawCursorAndText_Info(y, TRUE); + DrawCursorAndText_Menu(choice - first_entry, choice, FALSE); + DrawCursorAndText_Menu(y, first_entry + y, TRUE); - choice = choice_store[info_mode] = y; + choice = choice_store[mode] = first_entry + y; } } - else if (!(info_info[y].type & TYPE_GHOSTED)) + else if (!(menu_info[first_entry + y].type & TYPE_GHOSTED)) { PlaySound(SND_MENU_ITEM_SELECTING); - if (info_info[y].type & TYPE_ENTER_OR_LEAVE) + /* when selecting key headline, execute function for key value change */ + if (menu_info[first_entry + y].type & TYPE_KEYTEXT && + menu_info[first_entry + y + 1].type & TYPE_KEY) + y++; + + /* when selecting string value, execute function for list selection */ + if (menu_info[first_entry + y].type & TYPE_STRING && y > 0 && + menu_info[first_entry + y - 1].type & TYPE_ENTER_LIST) + y--; + + if (menu_info[first_entry + y].type & TYPE_ENTER_OR_LEAVE) { - void (*menu_callback_function)(void) = info_info[choice].value; + void (*menu_callback_function)(void) = + menu_info[first_entry + y].value; - FadeSetFromType(info_info[y].type); + FadeSetFromType(menu_info[first_entry + y].type); menu_callback_function(); } + else if (menu_info[first_entry + y].type & TYPE_VALUE && + menu_info == setup_info) + { + changeSetupValue(y, first_entry + y, dx); + } } } } +void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button) +{ + menu_info = info_info; + + HandleMenuScreen(mx, my, dx, dy, button, + info_mode, num_info_info, max_info_info); +} + void DrawInfoScreen_NotAvailable(char *text_title, char *text_error) { int ystart1 = mSY - SY + 100; int ystart2 = mSY - SY + 150; int ybottom = mSY - SY + SYSIZE - 20; - SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET); + SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO); FadeOut(REDRAW_FIELD); @@ -2264,6 +2665,9 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos) void DrawInfoScreen_TitleScreen() { + game_status_last_screen = GAME_MODE_INFO; + game_status = GAME_MODE_TITLE; + DrawTitleScreen(); } @@ -2341,7 +2745,7 @@ void HandleInfoScreen_Elements(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } @@ -2440,7 +2844,7 @@ void HandleInfoScreen_Music(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } @@ -2620,7 +3024,7 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr) DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, "and"); DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, - "Jürgen Bonhagen"); + "J\xfcrgen Bonhagen"); DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, "for the continuous creation"); DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_2, @@ -2674,7 +3078,7 @@ static void DrawInfoScreen_CreditsScreen(int screen_nr) DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, "Thanks to"); DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, - "Karl Hörnell"); + "Karl H\xf6rnell"); DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, "for some additional toons"); } @@ -2744,7 +3148,7 @@ void HandleInfoScreen_Credits(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } @@ -2787,11 +3191,11 @@ void DrawInfoScreen_Program() DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2, "If you like it, send e-mail to:"); DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3, - PROGRAM_EMAIL_STRING); + setup.internal.program_email); DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, "More information and levels:"); DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, - PROGRAM_WEBSITE_STRING); + setup.internal.program_website); DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2, "If you have created new levels,"); DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_2, @@ -2823,7 +3227,7 @@ void HandleInfoScreen_Program(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -2863,7 +3267,7 @@ void DrawInfoScreen_Version() DrawTextSCentered(ystart1, FONT_TEXT_1, "Version Information:"); DrawTextF(xstart1, ystart2, font_header, "Name"); - DrawTextF(xstart2, ystart2, font_text, PROGRAM_TITLE_STRING); + DrawTextF(xstart2, ystart2, font_text, getProgramTitleString()); ystart2 += ystep; DrawTextF(xstart1, ystart2, font_header, "Version"); @@ -2998,7 +3402,7 @@ void HandleInfoScreen_Version(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -3010,6 +3414,41 @@ void DrawInfoScreen_LevelSet() { struct TitleMessageInfo *tmi = &readme; char *filename = getLevelSetInfoFilename(); + char *title = "Level Set Information:"; + int ystart1 = mSY - SY + 100; + int ybottom = mSY - SY + SYSIZE - 20; + + if (filename == NULL) + { + DrawInfoScreen_NotAvailable(title, "No information for this level set."); + + return; + } + + SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET); + + FadeOut(REDRAW_FIELD); + + ClearField(); + DrawHeadline(); + + DrawTextSCentered(ystart1, FONT_TEXT_1, title); + + /* if x position set to "-1", automatically determine by playfield width */ + if (tmi->x == -1) + tmi->x = SXSIZE / 2; + + /* if y position set to "-1", use static default value */ + if (tmi->y == -1) + tmi->y = 150; + + /* if width set to "-1", automatically determine by playfield width */ + if (tmi->width == -1) + tmi->width = SXSIZE - 2 * TILEX; + + /* if height set to "-1", automatically determine by playfield height */ + if (tmi->height == -1) + tmi->height = SYSIZE - 20 - tmi->y - 10; /* if chars set to "-1", automatically determine by text and font width */ if (tmi->chars == -1) @@ -3023,25 +3462,12 @@ void DrawInfoScreen_LevelSet() else tmi->height = tmi->lines * getFontHeight(tmi->font); - SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_LEVELSET); - - FadeOut(REDRAW_FIELD); - - ClearField(); - DrawHeadline(); - - DrawTextCentered(mSY + 100, FONT_TEXT_1, "Level Set Information:"); - - if (filename != NULL) - DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi), - filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1, - tmi->autowrap, tmi->centered, tmi->parse_comments); - else - DrawTextCentered(mSY + ALIGNED_TEXT_YPOS(tmi), FONT_TEXT_2, - "No information for this level set."); + DrawTextFile(mSX + ALIGNED_TEXT_XPOS(tmi), mSY + ALIGNED_TEXT_YPOS(tmi), + filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1, + tmi->autowrap, tmi->centered, tmi->parse_comments); - DrawTextCentered(mSY + SYSIZE - 20, FONT_TEXT_4, - "Press any key or button for info menu"); + DrawTextSCentered(ybottom, FONT_TEXT_4, + "Press any key or button for info menu"); FadeIn(REDRAW_FIELD); } @@ -3064,7 +3490,7 @@ void HandleInfoScreen_LevelSet(int button) FadeSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -3072,7 +3498,7 @@ void HandleInfoScreen_LevelSet(int button) } } -static void DrawInfoScreenExt(int fade_mask, boolean do_fading) +static void DrawInfoScreen() { SetMainBackgroundImage(IMG_BACKGROUND_INFO); @@ -3091,7 +3517,7 @@ static void DrawInfoScreenExt(int fade_mask, boolean do_fading) else if (info_mode == INFO_MODE_LEVELSET) DrawInfoScreen_LevelSet(); else - DrawInfoScreen_Main(fade_mask, do_fading); + DrawInfoScreen_Main(); if (info_mode != INFO_MODE_MAIN && info_mode != INFO_MODE_TITLE && @@ -3102,16 +3528,6 @@ static void DrawInfoScreenExt(int fade_mask, boolean do_fading) } } -void DrawAndFadeInInfoScreen(int fade_mask) -{ - DrawInfoScreenExt(fade_mask, TRUE); -} - -void DrawInfoScreen() -{ - DrawInfoScreenExt(REDRAW_FIELD, FALSE); -} - void HandleInfoScreen(int mx, int my, int dx, int dy, int button) { if (info_mode == INFO_MODE_TITLE) @@ -3159,6 +3575,10 @@ void HandleTypeName(int newxpos, Key key) strcpy(last_player_name, setup.player_name); xpos = newxpos; + +#if defined(TARGET_SDL2) + SDL_StartTextInput(); +#endif } else if (is_valid_key_char && xpos < MAX_PLAYER_NAME_LEN) { @@ -3204,6 +3624,10 @@ void HandleTypeName(int newxpos, Key key) startx = mSX + ALIGNED_TEXT_XPOS(pos); DrawText(startx, starty, setup.player_name, font_nr); + +#if defined(TARGET_SDL2) + SDL_StopTextInput(); +#endif } } @@ -3214,6 +3638,20 @@ void HandleTypeName(int newxpos, Key key) static void DrawChooseTree(TreeInfo **ti_ptr) { + int fade_mask = REDRAW_FIELD; + + if (CheckIfGlobalBorderHasChanged()) + fade_mask = REDRAW_ALL; + + if (strEqual((*ti_ptr)->subdir, STRING_TOP_DIRECTORY)) + { + game_status = GAME_MODE_MAIN; + + DrawMainMenu(); + + return; + } + UnmapAllGadgets(); FreeScreenGadgets(); @@ -3221,35 +3659,20 @@ static void DrawChooseTree(TreeInfo **ti_ptr) CloseDoor(DOOR_CLOSE_2); - FadeOut(REDRAW_FIELD); + FadeOut(fade_mask); + + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); ClearField(); HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr); MapScreenTreeGadgets(*ti_ptr); - FadeIn(REDRAW_FIELD); - - InitAnimation(); -} - -static void AdjustScrollbar(int id, int items_max, int items_visible, - int item_position) -{ - struct GadgetInfo *gi = screen_gadget[id]; - - if (item_position > items_max - items_visible) - item_position = items_max - items_visible; + DrawMaskedBorder(fade_mask); - ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max, - GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible, - GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END); -} + FadeIn(fade_mask); -static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti) -{ - AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN, - first_entry); + InitAnimation(); } static void drawChooseTreeList(int first_entry, int num_page_entries, @@ -3267,10 +3690,7 @@ static void drawChooseTreeList(int first_entry, int num_page_entries, DrawTextSCentered(mSY - SY + yoffset, FONT_TITLE_1, title_string); - /* clear tree list area, but not title or scrollbar */ - DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32, - SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset, - NUM_MENU_ENTRIES_ON_SCREEN * 32); + clearMenuListArea(); for (i = 0; i < num_page_entries; i++) { @@ -3339,7 +3759,7 @@ static void drawChooseTreeInfo(int entry_pos, TreeInfo *ti) node->class_desc); /* let BackToFront() redraw only what is needed */ - redraw_mask = last_redraw_mask | REDRAW_TILES; + redraw_mask = last_redraw_mask; for (x = 0; x < SCR_FIELDX; x++) MarkTileDirty(x, 1); } @@ -3409,7 +3829,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, else if (game_status == GAME_MODE_SETUP) { if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || - setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) + setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY || + setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) execSetupGame(); else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE || setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE || @@ -3429,11 +3850,15 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, else { if (game_status == GAME_MODE_LEVELNR) - level_nr = atoi(level_number_current->identifier); + { + int new_level_nr = atoi(level_number_current->identifier); + + HandleMainMenu_SelectLevel(0, 0, new_level_nr); + } game_status = GAME_MODE_MAIN; - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } return; @@ -3497,7 +3922,6 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, ti->cl_first, ti); } - return; } @@ -3540,7 +3964,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, } if (!anyScrollbarGadgetActive() && - IN_VIS_FIELD(x, y) && + IN_VIS_MENU(x, y) && mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x && y >= 0 && y < num_page_entries) { @@ -3603,7 +4027,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, if (game_status == GAME_MODE_SETUP) { if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED || - setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) + setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY || + setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) execSetupGame(); else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE || setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE || @@ -3623,7 +4048,11 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, else { if (game_status == GAME_MODE_LEVELNR) - level_nr = atoi(level_number_current->identifier); + { + int new_level_nr = atoi(level_number_current->identifier); + + HandleMainMenu_SelectLevel(0, 0, new_level_nr); + } game_status = GAME_MODE_MAIN; @@ -3712,6 +4141,17 @@ void HandleChooseLevelNr(int mx, int my, int dx, int dy, int button) void DrawHallOfFame(int highlight_position) { + int fade_mask = REDRAW_FIELD; + + /* required before door position may be changed in next step */ + CloseDoor(DOOR_CLOSE_ALL); + + /* needed if different viewport properties defined for scores */ + ChangeViewportPropertiesIfNeeded(); + + if (CheckIfGlobalBorderHasChanged()) + fade_mask = REDRAW_ALL; + UnmapAllGadgets(); FadeSoundsAndMusic(); @@ -3723,23 +4163,25 @@ void DrawHallOfFame(int highlight_position) SetDrawDeactivationMask(REDRAW_NONE); SetDrawBackgroundMask(REDRAW_FIELD); - CloseDoor(DOOR_CLOSE_2); - if (highlight_position < 0) LoadScore(level_nr); FadeSetEnterScreen(); - FadeOut(REDRAW_FIELD); + FadeOut(fade_mask); InitAnimation(); PlayMenuSound(); PlayMenuMusic(); + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + HandleHallOfFame(highlight_position, 0, 0, 0, MB_MENU_INITIALIZE); - FadeIn(REDRAW_FIELD); + DrawMaskedBorder(fade_mask); + + FadeIn(fade_mask); } static void drawHallOfFameList(int first_entry, int highlight_position) @@ -3840,7 +4282,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button) game_status = GAME_MODE_MAIN; - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); } if (game_status == GAME_MODE_SCORES) @@ -3860,6 +4302,7 @@ static char *screen_mode_text; static char *window_size_text; static char *scaling_type_text; static char *scroll_delay_text; +static char *snapshot_mode_text; static char *game_speed_text; static char *graphics_set_name; static char *sounds_set_name; @@ -3978,10 +4421,61 @@ static void execSetupGame_setScrollDelays() scroll_delay_text = scroll_delay_current->name; } +static void execSetupGame_setSnapshotModes() +{ + if (snapshot_modes == NULL) + { + int i; + + for (i = 0; snapshot_modes_list[i].value != NULL; i++) + { + TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); + char identifier[32], name[32]; + char *value = snapshot_modes_list[i].value; + char *text = snapshot_modes_list[i].text; + + ti->node_top = &snapshot_modes; + ti->sort_priority = i; + + sprintf(identifier, "%s", value); + sprintf(name, "%s", text); + + setString(&ti->identifier, identifier); + setString(&ti->name, name); + setString(&ti->name_sorting, name); + setString(&ti->infotext, "Snapshot Mode"); + + pushTreeInfo(&snapshot_modes, ti); + } + + /* sort snapshot mode values to start with lowest snapshot mode value */ + sortTreeInfo(&snapshot_modes); + + /* set current snapshot mode value to configured snapshot mode value */ + snapshot_mode_current = + getTreeInfoFromIdentifier(snapshot_modes, setup.engine_snapshot_mode); + + /* if that fails, set current snapshot mode to reliable default value */ + if (snapshot_mode_current == NULL) + snapshot_mode_current = + getTreeInfoFromIdentifier(snapshot_modes, STR_SNAPSHOT_MODE_DEFAULT); + + /* if that also fails, set current snapshot mode to first available value */ + if (snapshot_mode_current == NULL) + snapshot_mode_current = snapshot_modes; + } + + setup.engine_snapshot_mode = snapshot_mode_current->identifier; + + /* needed for displaying snapshot mode text instead of identifier */ + snapshot_mode_text = snapshot_mode_current->name; +} + static void execSetupGame() { execSetupGame_setGameSpeeds(); execSetupGame_setScrollDelays(); + execSetupGame_setSnapshotModes(); setup_mode = SETUP_MODE_GAME; @@ -4002,14 +4496,21 @@ static void execSetupChooseScrollDelay() DrawSetupScreen(); } -static void execSetupEditor() +static void execSetupChooseSnapshotMode() { - setup_mode = SETUP_MODE_EDITOR; + setup_mode = SETUP_MODE_CHOOSE_SNAPSHOT_MODE; DrawSetupScreen(); } -static void execSetupGraphics_setWindowSizes(boolean update_list) +static void execSetupEditor() +{ + setup_mode = SETUP_MODE_EDITOR; + + DrawSetupScreen(); +} + +static void execSetupGraphics_setWindowSizes(boolean update_list) { if (window_sizes != NULL && update_list) { @@ -4288,6 +4789,7 @@ static void execSetupSound() { if (volumes_simple == NULL) { + boolean current_volume_simple_found = FALSE; int i; for (i = 0; volumes_list[i].value != -1; i++) @@ -4309,6 +4811,31 @@ static void execSetupSound() setString(&ti->infotext, "Sound Volume"); pushTreeInfo(&volumes_simple, ti); + + if (value == setup.volume_simple) + current_volume_simple_found = TRUE; + } + + if (!current_volume_simple_found) + { + // add entry for non-preset volume value + + TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); + char identifier[32], name[32]; + int value = setup.volume_simple; + + ti->node_top = &volumes_simple; + ti->sort_priority = value; + + sprintf(identifier, "%d", value); + sprintf(name, "%d %% (Current)", value); + + setString(&ti->identifier, identifier); + setString(&ti->name, name); + setString(&ti->name_sorting, name); + setString(&ti->infotext, "Sound Volume"); + + pushTreeInfo(&volumes_simple, ti); } /* sort volume values to start with lowest volume value */ @@ -4330,6 +4857,7 @@ static void execSetupSound() if (volumes_loops == NULL) { + boolean current_volume_loops_found = FALSE; int i; for (i = 0; volumes_list[i].value != -1; i++) @@ -4351,6 +4879,31 @@ static void execSetupSound() setString(&ti->infotext, "Loops Volume"); pushTreeInfo(&volumes_loops, ti); + + if (value == setup.volume_loops) + current_volume_loops_found = TRUE; + } + + if (!current_volume_loops_found) + { + // add entry for non-preset volume value + + TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); + char identifier[32], name[32]; + int value = setup.volume_loops; + + ti->node_top = &volumes_loops; + ti->sort_priority = value; + + sprintf(identifier, "%d", value); + sprintf(name, "%d %% (Current)", value); + + setString(&ti->identifier, identifier); + setString(&ti->name, name); + setString(&ti->name_sorting, name); + setString(&ti->infotext, "Loops Volume"); + + pushTreeInfo(&volumes_loops, ti); } /* sort volume values to start with lowest volume value */ @@ -4372,6 +4925,7 @@ static void execSetupSound() if (volumes_music == NULL) { + boolean current_volume_music_found = FALSE; int i; for (i = 0; volumes_list[i].value != -1; i++) @@ -4393,6 +4947,31 @@ static void execSetupSound() setString(&ti->infotext, "Music Volume"); pushTreeInfo(&volumes_music, ti); + + if (value == setup.volume_music) + current_volume_music_found = TRUE; + } + + if (!current_volume_music_found) + { + // add entry for non-preset volume value + + TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); + char identifier[32], name[32]; + int value = setup.volume_music; + + ti->node_top = &volumes_music; + ti->sort_priority = value; + + sprintf(identifier, "%d", value); + sprintf(name, "%d %% (Current)", value); + + setString(&ti->identifier, identifier); + setString(&ti->name, name); + setString(&ti->name_sorting, name); + setString(&ti->infotext, "Music Volume"); + + pushTreeInfo(&volumes_music, ti); } /* sort volume values to start with lowest volume value */ @@ -4638,12 +5217,14 @@ static void execSetupChooseMusic() DrawSetupScreen(); } +#if !defined(PLATFORM_ANDROID) static void execSetupInput() { setup_mode = SETUP_MODE_INPUT; DrawSetupScreen(); } +#endif static void execSetupShortcuts() { @@ -4691,7 +5272,7 @@ static void execExitSetup() { game_status = GAME_MODE_MAIN; - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } static void execSaveAndExitSetup() @@ -4735,6 +5316,9 @@ static struct TokenInfo setup_info_game[] = { TYPE_ENTER_LIST, execSetupChooseScrollDelay, "Scroll Delay:" }, { TYPE_STRING, &scroll_delay_text, "" }, #endif + { TYPE_ENTER_LIST, execSetupChooseSnapshotMode,"Game Engine Snapshot Mode:" }, + { TYPE_STRING, &snapshot_mode_text, "" }, + { TYPE_SWITCH, &setup.show_snapshot_buttons,"Show Snapshot Buttons:" }, { TYPE_EMPTY, NULL, "" }, { TYPE_LEAVE_MENU, execSetupMain, "Back" }, @@ -5022,20 +5606,6 @@ static Key getSetupKey() return key; } -static int getSetupTextFont(int type) -{ - if (type & (TYPE_SWITCH | - TYPE_YES_NO | - TYPE_YES_NO_AUTO | - TYPE_STRING | - TYPE_ECS_AGA | - TYPE_KEYTEXT | - TYPE_ENTER_LIST)) - return FONT_MENU_2; - else - return FONT_MENU_1; -} - static int getSetupValueFont(int type, void *value) { if (type & TYPE_KEY) @@ -5111,7 +5681,7 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw) int font1_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset; int font2_xoffset = getFontBitmapInfo(check_font_nr)->draw_xoffset; int text_startx = mSX + MENU_SCREEN_START_XPOS * 32; - int text_font_nr = getSetupTextFont(FONT_MENU_2); + int text_font_nr = getMenuTextFont(FONT_MENU_2); int text_font_xoffset = getFontBitmapInfo(text_font_nr)->draw_xoffset; int text_width = max_menu_text_length_medium * getFontWidth(text_font_nr); boolean correct_font_draw_xoffset = FALSE; @@ -5186,82 +5756,16 @@ static void changeSetupValue(int screen_pos, int setup_info_pos_raw, int dx) ToggleFullscreenOrChangeWindowScalingIfNeeded(); } -static void DrawCursorAndText_Setup(int screen_pos, int setup_info_pos_raw, - boolean active) -{ - int si_pos = (setup_info_pos_raw < 0 ? screen_pos : setup_info_pos_raw); - struct TokenInfo *si = &setup_info[si_pos]; - int xpos = MENU_SCREEN_START_XPOS; - int ypos = MENU_SCREEN_START_YPOS + screen_pos; - int font_nr = getSetupTextFont(si->type); - - if (setup_info == setup_info_input) - font_nr = FONT_MENU_1; - - if (active) - font_nr = FONT_ACTIVE(font_nr); - - DrawText(mSX + xpos * 32, mSY + ypos * 32, si->text, font_nr); - - if (si->type & ~TYPE_SKIP_ENTRY) - drawCursor(screen_pos, active); -} - -static void drawSetupInfoList(struct TokenInfo *setup_info, - int first_entry, int num_page_entries) -{ - int i; - - if (num_page_entries > NUM_MENU_ENTRIES_ON_SCREEN) - num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN; - - if (num_page_entries > max_setup_info) - num_page_entries = max_setup_info; - - if (first_entry + num_page_entries > max_setup_info) - first_entry = 0; - - /* clear tree list area, but not title or scrollbar */ - DrawBackground(mSX, mSY + MENU_SCREEN_START_YPOS * 32, - SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset, - NUM_MENU_ENTRIES_ON_SCREEN * 32); - - for (i = 0; i < num_page_entries; i++) - { - int setup_info_pos = first_entry + i; - struct TokenInfo *si = &setup_info[setup_info_pos]; - void *value_ptr = si->value; - - /* set some entries to "unchangeable" according to other variables */ - if ((value_ptr == &setup.sound_simple && !audio.sound_available) || - (value_ptr == &setup.sound_loops && !audio.loops_available) || - (value_ptr == &setup.sound_music && !audio.music_available) || - (value_ptr == &setup.fullscreen && !video.fullscreen_available) || - (value_ptr == &screen_mode_text && !video.fullscreen_available) || - (value_ptr == &window_size_text && !video.window_scaling_available) || - (value_ptr == &scaling_type_text && !video.window_scaling_available)) - si->type |= TYPE_GHOSTED; - - if (si->type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST)) - initCursor(i, IMG_MENU_BUTTON_ENTER_MENU); - else if (si->type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) - initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); - else if (si->type & ~TYPE_SKIP_ENTRY) - initCursor(i, IMG_MENU_BUTTON); - - DrawCursorAndText_Setup(i, setup_info_pos, FALSE); - - if (si->type & TYPE_VALUE) - drawSetupValue(i, setup_info_pos); - } -} - static void DrawSetupScreen_Generic() { + int fade_mask = REDRAW_FIELD; boolean redraw_all = FALSE; char *title_string = NULL; int i; + if (CheckIfGlobalBorderHasChanged()) + fade_mask = REDRAW_ALL; + UnmapAllGadgets(); FreeScreenGadgets(); @@ -5272,7 +5776,9 @@ static void DrawSetupScreen_Generic() if (redraw_mask & REDRAW_ALL) redraw_all = TRUE; - FadeOut(REDRAW_FIELD); + FadeOut(fade_mask); + + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); ClearField(); @@ -5359,271 +5865,21 @@ static void DrawSetupScreen_Generic() MapScreenGadgets(max_setup_info); if (redraw_all) - redraw_mask = REDRAW_ALL; + redraw_mask = fade_mask = REDRAW_ALL; + + DrawMaskedBorder(fade_mask); - FadeIn(redraw_mask); + FadeIn(fade_mask); InitAnimation(); } void HandleSetupScreen_Generic(int mx, int my, int dx, int dy, int button) { - static int choice_store[MAX_SETUP_MODES]; - static int first_entry_store[MAX_SETUP_MODES]; - int choice = choice_store[setup_mode]; /* starts with 0 */ - int first_entry = first_entry_store[setup_mode]; /* starts with 0 */ - int x = 0; - int y = choice - first_entry; - int y_old = y; - boolean position_set_by_scrollbar = (dx == 999); - int step = (button == 1 ? 1 : button == 2 ? 5 : 10); - int num_page_entries; - - num_page_entries = MIN(max_setup_info, NUM_MENU_ENTRIES_ON_SCREEN); + menu_info = setup_info; - if (button == MB_MENU_INITIALIZE) - { - /* advance to first valid menu entry */ - while (choice < num_setup_info && - setup_info[choice].type & TYPE_SKIP_ENTRY) - choice++; - - if (position_set_by_scrollbar) - first_entry = first_entry_store[setup_mode] = dy; - else - AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_setup_info, - NUM_MENU_ENTRIES_ON_SCREEN, first_entry); - - drawSetupInfoList(setup_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN); - - if (choice < first_entry) - { - choice = first_entry; - - if (setup_info[choice].type & TYPE_SKIP_ENTRY) - choice++; - } - else if (choice > first_entry + num_page_entries - 1) - { - choice = first_entry + num_page_entries - 1; - - if (setup_info[choice].type & TYPE_SKIP_ENTRY) - choice--; - } - - choice_store[setup_mode] = choice; - - DrawCursorAndText_Setup(choice - first_entry, choice, TRUE); - - return; - } - else if (button == MB_MENU_LEAVE) - { - int i; - - PlaySound(SND_MENU_ITEM_SELECTING); - - for (i = 0; setup_info[i].type != 0; i++) - { - if (setup_info[i].type & TYPE_LEAVE_MENU) - { - void (*menu_callback_function)(void) = setup_info[i].value; - - FadeSetLeaveMenu(); - - menu_callback_function(); - - break; /* absolutely needed because function changes 'setup_info'! */ - } - } - - return; - } - - if (mx || my) /* mouse input */ - { - x = (mx - mSX) / 32; - y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS; - } - else if (dx || dy) /* keyboard or scrollbar/scrollbutton input */ - { - /* move cursor instead of scrolling when already at start/end of list */ - if (dy == -1 * SCROLL_LINE && first_entry == 0) - dy = -1; - else if (dy == +1 * SCROLL_LINE && - first_entry + num_page_entries == max_setup_info) - dy = 1; - - /* handle scrolling screen one line or page */ - if (y + dy < 0 || - y + dy > num_page_entries - 1) - { - boolean redraw = FALSE; - - if (ABS(dy) == SCROLL_PAGE) - step = num_page_entries - 1; - - if (dy < 0 && first_entry > 0) - { - /* scroll page/line up */ - - first_entry -= step; - if (first_entry < 0) - first_entry = 0; - - redraw = TRUE; - } - else if (dy > 0 && first_entry + num_page_entries < max_setup_info) - { - /* scroll page/line down */ - - first_entry += step; - if (first_entry + num_page_entries > max_setup_info) - first_entry = MAX(0, max_setup_info - num_page_entries); - - redraw = TRUE; - } - - if (redraw) - { - choice += first_entry - first_entry_store[setup_mode]; - - if (choice < first_entry) - { - choice = first_entry; - - if (setup_info[choice].type & TYPE_SKIP_ENTRY) - choice++; - } - else if (choice > first_entry + num_page_entries - 1) - { - choice = first_entry + num_page_entries - 1; - - if (setup_info[choice].type & TYPE_SKIP_ENTRY) - choice--; - } - else if (setup_info[choice].type & TYPE_SKIP_ENTRY) - { - choice += SIGN(dy); - - if (choice < first_entry || - choice > first_entry + num_page_entries - 1) - first_entry += SIGN(dy); - } - - first_entry_store[setup_mode] = first_entry; - choice_store[setup_mode] = choice; - - drawSetupInfoList(setup_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN); - - DrawCursorAndText_Setup(choice - first_entry, choice, TRUE); - - AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_setup_info, - NUM_MENU_ENTRIES_ON_SCREEN, first_entry); - } - - return; - } - - if (dx) - { - int menu_navigation_type = (dx < 0 ? TYPE_LEAVE : TYPE_ENTER); - - if (setup_info[choice].type & menu_navigation_type || - setup_info[choice].type & TYPE_BOOLEAN_STYLE || - setup_info[choice].type & TYPE_YES_NO_AUTO) - button = MB_MENU_CHOICE; - } - else if (dy) - y += dy; - - /* jump to next non-empty menu entry (up or down) */ - while (first_entry + y > 0 && - first_entry + y < max_setup_info - 1 && - setup_info[first_entry + y].type & TYPE_SKIP_ENTRY) - y += dy; - - if (!IN_VIS_FIELD(x, y)) - { - choice += y - y_old; - - if (choice < first_entry) - first_entry = choice; - else if (choice > first_entry + num_page_entries - 1) - first_entry = choice - num_page_entries + 1; - - if (first_entry >= 0 && - first_entry + num_page_entries <= max_setup_info) - { - first_entry_store[setup_mode] = first_entry; - - if (choice < first_entry) - choice = first_entry; - else if (choice > first_entry + num_page_entries - 1) - choice = first_entry + num_page_entries - 1; - - choice_store[setup_mode] = choice; - - drawSetupInfoList(setup_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN); - - DrawCursorAndText_Setup(choice - first_entry, choice, TRUE); - - AdjustScrollbar(SCREEN_CTRL_ID_SCROLL_VERTICAL, max_setup_info, - NUM_MENU_ENTRIES_ON_SCREEN, first_entry); - } - - return; - } - } - - if (!anyScrollbarGadgetActive() && - IN_VIS_FIELD(x, y) && - mx < screen_gadget[SCREEN_CTRL_ID_SCROLL_VERTICAL]->x && - y >= 0 && y < num_page_entries) - { - if (button) - { - if (first_entry + y != choice && - setup_info[first_entry + y].type & ~TYPE_SKIP_ENTRY) - { - PlaySound(SND_MENU_ITEM_ACTIVATING); - - DrawCursorAndText_Setup(choice - first_entry, choice, FALSE); - DrawCursorAndText_Setup(y, first_entry + y, TRUE); - - choice = choice_store[setup_mode] = first_entry + y; - } - } - else if (!(setup_info[first_entry + y].type & TYPE_GHOSTED)) - { - PlaySound(SND_MENU_ITEM_SELECTING); - - /* when selecting key headline, execute function for key value change */ - if (setup_info[first_entry + y].type & TYPE_KEYTEXT && - setup_info[first_entry + y + 1].type & TYPE_KEY) - y++; - - /* when selecting string value, execute function for list selection */ - if (setup_info[first_entry + y].type & TYPE_STRING && y > 0 && - setup_info[first_entry + y - 1].type & TYPE_ENTER_LIST) - y--; - - if (setup_info[first_entry + y].type & TYPE_ENTER_OR_LEAVE) - { - void (*menu_callback_function)(void) = - setup_info[first_entry + y].value; - - FadeSetFromType(setup_info[first_entry + y].type); - - menu_callback_function(); - } - else - { - if (setup_info[first_entry + y].type & TYPE_VALUE) - changeSetupValue(y, first_entry + y, dx); - } - } - } + HandleMenuScreen(mx, my, dx, dy, button, + setup_mode, num_setup_info, max_setup_info); } void DrawSetupScreen_Input() @@ -5840,7 +6096,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button) { HandleSetupScreen_Input_Player(1, dx < 0 ? -1 : +1); } - else if (IN_VIS_FIELD(x, y) && + else if (IN_VIS_FIELD(x, y) && // (does not use "IN_VIS_MENU()" yet) y >= pos_start && y <= pos_end && !(y >= pos_empty1 && y <= pos_empty2)) { @@ -6252,6 +6508,8 @@ void DrawSetupScreen() DrawChooseTree(&game_speed_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) DrawChooseTree(&scroll_delay_current); + else if (setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) + DrawChooseTree(&snapshot_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE) DrawChooseTree(&screen_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE) @@ -6303,6 +6561,8 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button) HandleChooseTree(mx, my, dx, dy, button, &game_speed_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCROLL_DELAY) HandleChooseTree(mx, my, dx, dy, button, &scroll_delay_current); + else if (setup_mode == SETUP_MODE_CHOOSE_SNAPSHOT_MODE) + HandleChooseTree(mx, my, dx, dy, button, &snapshot_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCREEN_MODE) HandleChooseTree(mx, my, dx, dy, button, &screen_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE) @@ -6535,6 +6795,10 @@ static void CreateScreenScrollbuttons() width = SC_SCROLLBUTTON_XSIZE; height = SC_SCROLLBUTTON_YSIZE; + /* correct scrollbar position if placed outside menu (playfield) area */ + if (x > SX + SC_SCROLL_UP_XPOS) + x = SX + SC_SCROLL_UP_XPOS; + if (id == SCREEN_CTRL_ID_SCROLL_DOWN) y = mSY + (SC_SCROLL_VERTICAL_YPOS + (NUM_MENU_ENTRIES_ON_SCREEN - 2) * SC_SCROLLBUTTON_YSIZE); @@ -6600,6 +6864,10 @@ static void CreateScreenScrollbars() width = scrollbar_info[i].width; height = scrollbar_info[i].height; + /* correct scrollbar position if placed outside menu (playfield) area */ + if (x > SX + SC_SCROLL_VERTICAL_XPOS) + x = SX + SC_SCROLL_VERTICAL_XPOS; + if (id == SCREEN_CTRL_ID_SCROLL_VERTICAL) height = (NUM_MENU_ENTRIES_ON_SCREEN - 2) * SC_SCROLLBUTTON_YSIZE; @@ -6704,11 +6972,11 @@ static void HandleScreenGadgets(struct GadgetInfo *gi) switch (id) { case SCREEN_CTRL_ID_PREV_LEVEL: - HandleMainMenu_SelectLevel(step, -1); + HandleMainMenu_SelectLevel(step, -1, NO_DIRECT_LEVEL_SELECT); break; case SCREEN_CTRL_ID_NEXT_LEVEL: - HandleMainMenu_SelectLevel(step, +1); + HandleMainMenu_SelectLevel(step, +1, NO_DIRECT_LEVEL_SELECT); break; case SCREEN_CTRL_ID_PREV_PLAYER: @@ -6726,6 +6994,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi) HandleChooseLevelNr(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK); else if (game_status == GAME_MODE_SETUP) HandleSetupScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK); + else if (game_status == GAME_MODE_INFO) + HandleInfoScreen(0,0, 0, -1 * SCROLL_LINE, MB_MENU_MARK); break; case SCREEN_CTRL_ID_SCROLL_DOWN: @@ -6735,6 +7005,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi) HandleChooseLevelNr(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK); else if (game_status == GAME_MODE_SETUP) HandleSetupScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK); + else if (game_status == GAME_MODE_INFO) + HandleInfoScreen(0,0, 0, +1 * SCROLL_LINE, MB_MENU_MARK); break; case SCREEN_CTRL_ID_SCROLL_VERTICAL: @@ -6744,6 +7016,8 @@ static void HandleScreenGadgets(struct GadgetInfo *gi) HandleChooseLevelNr(0,0,999,gi->event.item_position,MB_MENU_INITIALIZE); else if (game_status == GAME_MODE_SETUP) HandleSetupScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE); + else if (game_status == GAME_MODE_INFO) + HandleInfoScreen(0,0, 999,gi->event.item_position,MB_MENU_INITIALIZE); break; default: