X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fscreens.c;h=9c02fc9e3a7f697a1792f00656d9e77d3de7b393;hp=c9c2ba4a29799f65f8be8025408f260e9e4ee051;hb=5c6c42f1;hpb=ce49fdb87ac8d3d9f258882f3072cad48a940044 diff --git a/src/screens.c b/src/screens.c index c9c2ba4a..9c02fc9e 100644 --- a/src/screens.c +++ b/src/screens.c @@ -18,11 +18,15 @@ #include "editor.h" #include "files.h" #include "tape.h" -#include "cartoons.h" +#include "anim.h" #include "network.h" #include "init.h" #include "config.h" + +#define DEBUG_JOYSTICKS 0 + + /* screens on the info screen */ #define INFO_MODE_MAIN 0 #define INFO_MODE_TITLE 1 @@ -61,9 +65,9 @@ #define SETUP_MODE_CHOOSE_GAME_SPEED 16 #define SETUP_MODE_CHOOSE_SCROLL_DELAY 17 #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_WINDOW_SIZE 19 +#define SETUP_MODE_CHOOSE_SCALING_TYPE 20 +#define SETUP_MODE_CHOOSE_RENDERING 21 #define SETUP_MODE_CHOOSE_GRAPHICS 22 #define SETUP_MODE_CHOOSE_SOUNDS 23 #define SETUP_MODE_CHOOSE_MUSIC 24 @@ -76,12 +80,17 @@ #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 #define SETUPINPUT_SCREEN_POS_END (SCR_FIELDY - 4) #define SETUPINPUT_SCREEN_POS_EMPTY1 (SETUPINPUT_SCREEN_POS_START + 3) #define SETUPINPUT_SCREEN_POS_EMPTY2 (SETUPINPUT_SCREEN_POS_END - 1) +#define MENU_SETUP_FONT_TITLE FONT_TEXT_1 +#define MENU_SETUP_FONT_TEXT FONT_TITLE_2 + /* for various menu stuff */ #define MENU_SCREEN_START_XPOS 1 #define MENU_SCREEN_START_YPOS 2 @@ -89,18 +98,31 @@ #define MENU_SCREEN_MAX_XPOS (SCR_FIELDX - 1) #define MENU_TITLE1_YPOS 8 #define MENU_TITLE2_YPOS 46 +#define MENU_INFO_FONT_TITLE FONT_TEXT_1 +#define MENU_INFO_FONT_HEAD FONT_TEXT_2 +#define MENU_INFO_FONT_TEXT FONT_TEXT_3 +#define MENU_INFO_FONT_FOOT FONT_TEXT_4 +#define MENU_INFO_SPACE_HEAD (menu.headline2_spacing_info[info_mode]) #define MENU_SCREEN_INFO_XSTART 16 #define MENU_SCREEN_INFO_YSTART1 100 -#define MENU_SCREEN_INFO_YSTART2 128 +#define MENU_SCREEN_INFO_YSTART2 (MENU_SCREEN_INFO_YSTART1 + \ + getMenuTextStep(MENU_INFO_SPACE_HEAD, \ + MENU_INFO_FONT_TITLE)) #define MENU_SCREEN_INFO_YSTEP (TILEY + 4) #define MENU_SCREEN_INFO_YBOTTOM (SYSIZE - 20) #define MENU_SCREEN_INFO_YSIZE (MENU_SCREEN_INFO_YBOTTOM - \ 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) @@ -155,7 +177,7 @@ static void HandleScreenGadgets(struct GadgetInfo *); static void HandleSetupScreen_Generic(int, int, int, int, int); static void HandleSetupScreen_Input(int, int, int, int, int); static void CustomizeKeyboard(int); -static void CalibrateJoystick(int); +static void ConfigureJoystick(int); static void execSetupGame(void); static void execSetupGraphics(void); static void execSetupSound(void); @@ -166,10 +188,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); @@ -190,15 +210,15 @@ static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS]; static int info_mode = INFO_MODE_MAIN; static int setup_mode = SETUP_MODE_MAIN; -static TreeInfo *screen_modes = NULL; -static TreeInfo *screen_mode_current = NULL; - static TreeInfo *window_sizes = NULL; static TreeInfo *window_size_current = NULL; static TreeInfo *scaling_types = NULL; static TreeInfo *scaling_type_current = NULL; +static TreeInfo *rendering_modes = NULL; +static TreeInfo *rendering_mode_current = NULL; + static TreeInfo *scroll_delays = NULL; static TreeInfo *scroll_delay_current = NULL; @@ -264,6 +284,23 @@ static struct { NULL, NULL }, }; +static struct +{ + char *value; + char *text; +} rendering_modes_list[] = +{ + { STR_SPECIAL_RENDERING_OFF, "Off (May show artifacts, fast)" }, + { STR_SPECIAL_RENDERING_BITMAP, "Bitmap/Texture mode (slower)" }, +#if DEBUG + // this mode may work under certain conditions, but does not work on Windows + { STR_SPECIAL_RENDERING_TARGET, "Target Texture mode (slower)" }, +#endif + { STR_SPECIAL_RENDERING_DOUBLE, "Double Texture mode (slower)" }, + + { NULL, NULL }, +}; + static struct { int value; @@ -320,11 +357,12 @@ static struct char *text; } snapshot_modes_list[] = { - { STR_SNAPSHOT_MODE_OFF, "Off" }, - { STR_SNAPSHOT_MODE_EVERY_STEP, "Every Step" }, - { STR_SNAPSHOT_MODE_EVERY_MOVE, "Every Move" }, + { STR_SNAPSHOT_MODE_OFF, "Off" }, + { STR_SNAPSHOT_MODE_EVERY_STEP, "Every Step" }, + { STR_SNAPSHOT_MODE_EVERY_MOVE, "Every Move" }, + { STR_SNAPSHOT_MODE_EVERY_COLLECT, "Every Collect" }, - { NULL, NULL }, + { NULL, NULL }, }; static struct @@ -359,6 +397,7 @@ static struct { { TOUCH_CONTROL_VIRTUAL_BUTTONS, "Virtual Buttons" }, { TOUCH_CONTROL_WIPE_GESTURES, "Wipe Gestures" }, + { TOUCH_CONTROL_FOLLOW_FINGER, "Follow Finger" }, { NULL, NULL }, }; @@ -388,7 +427,7 @@ static struct GAME_MODE_MAIN : GAME_MODE_DEFAULT) /* (there are no draw offset definitions needed for INFO_MODE_TITLE) */ -#define DRAW_MODE_INFO(i) ((i) >= INFO_MODE_ELEMENTS && \ +#define DRAW_MODE_INFO(i) ((i) >= INFO_MODE_TITLE && \ (i) <= INFO_MODE_LEVELSET ? (i) : \ INFO_MODE_MAIN) @@ -405,6 +444,9 @@ static struct #define DRAW_YOFFSET_INFO(i) (DRAW_MODE_INFO(i) == INFO_MODE_MAIN ? \ menu.draw_yoffset[GAME_MODE_INFO] : \ menu.draw_yoffset_info[DRAW_MODE_INFO(i)]) +#define EXTRA_SPACING_INFO(i) (DRAW_MODE_INFO(i) == INFO_MODE_MAIN ? \ + menu.extra_spacing[GAME_MODE_INFO] : \ + menu.extra_spacing_info[DRAW_MODE_INFO(i)]) #define DRAW_XOFFSET_SETUP(i) (DRAW_MODE_SETUP(i) == SETUP_MODE_MAIN ? \ menu.draw_xoffset[GAME_MODE_SETUP] : \ @@ -412,6 +454,9 @@ static struct #define DRAW_YOFFSET_SETUP(i) (DRAW_MODE_SETUP(i) == SETUP_MODE_MAIN ? \ menu.draw_yoffset[GAME_MODE_SETUP] : \ menu.draw_yoffset_setup[DRAW_MODE_SETUP(i)]) +#define EXTRA_SPACING_SETUP(i) (DRAW_MODE_SETUP(i) == SETUP_MODE_MAIN ? \ + menu.extra_spacing[GAME_MODE_SETUP] : \ + menu.extra_spacing_setup[DRAW_MODE_SETUP(i)]) #define DRAW_XOFFSET(s) ((s) == GAME_MODE_INFO ? \ DRAW_XOFFSET_INFO(info_mode) : \ @@ -423,6 +468,11 @@ static struct (s) == GAME_MODE_SETUP ? \ DRAW_YOFFSET_SETUP(setup_mode) : \ menu.draw_yoffset[DRAW_MODE(s)]) +#define EXTRA_SPACING(s) ((s) == GAME_MODE_INFO ? \ + EXTRA_SPACING_INFO(info_mode) : \ + (s) == GAME_MODE_SETUP ? \ + EXTRA_SPACING_SETUP(setup_mode) : \ + menu.extra_spacing[DRAW_MODE(s)]) #define mSX (SX + DRAW_XOFFSET(game_status)) #define mSY (SY + DRAW_YOFFSET(game_status)) @@ -449,6 +499,7 @@ struct TitleControlInfo { boolean is_image; boolean initial; + boolean first; int local_nr; int sort_priority; }; @@ -700,6 +751,13 @@ static int getTitleMessageGameMode(boolean initial) return (initial ? GAME_MODE_TITLE_INITIAL : GAME_MODE_TITLE); } +static int getTitleAnimMode(struct TitleControlInfo *tci) +{ + int base = (tci->initial ? GAME_MODE_TITLE_INITIAL_1 : GAME_MODE_TITLE_1); + + return base + tci->local_nr; +} + #if 0 static int getTitleScreenBackground(boolean initial) { @@ -797,44 +855,29 @@ static int getTitleMusic(struct TitleControlInfo *tci) static struct TitleFadingInfo getTitleFading(struct TitleControlInfo *tci) { boolean is_image = tci->is_image; - int initial = tci->initial; + boolean initial = tci->initial; + boolean first = tci->first; int nr = tci->local_nr; + struct TitleMessageInfo tmi; struct TitleFadingInfo ti; - if (is_image) - { - int graphic = getTitleScreenGraphic(nr, initial); - - /* initialize fading control values to default title config settings */ - ti = (initial ? title_initial_default : title_default); - - /* override default settings with image config settings, if defined */ - if (graphic_info[graphic].fade_mode != FADE_MODE_DEFAULT) - ti.fade_mode = graphic_info[graphic].fade_mode; - if (graphic_info[graphic].fade_delay > -1) - ti.fade_delay = graphic_info[graphic].fade_delay; - if (graphic_info[graphic].post_delay > -1) - ti.post_delay = graphic_info[graphic].post_delay; - if (graphic_info[graphic].auto_delay > -1) - ti.auto_delay = graphic_info[graphic].auto_delay; - } - else - { - if (initial) - { - ti.fade_mode = titlemessage_initial[nr].fade_mode; - ti.fade_delay = titlemessage_initial[nr].fade_delay; - ti.post_delay = titlemessage_initial[nr].post_delay; - ti.auto_delay = titlemessage_initial[nr].auto_delay; - } - else - { - ti.fade_mode = titlemessage[nr].fade_mode; - ti.fade_delay = titlemessage[nr].fade_delay; - ti.post_delay = titlemessage[nr].post_delay; - ti.auto_delay = titlemessage[nr].auto_delay; - } - } + tmi = (is_image ? (initial ? (first ? + titlescreen_initial_first[nr] : + titlescreen_initial[nr]) + : (first ? + titlescreen_first[nr] : + titlescreen[nr])) + : (initial ? (first ? + titlemessage_initial_first[nr] : + titlemessage_initial[nr]) + : (first ? + titlemessage_first[nr] : + titlemessage[nr]))); + + ti.fade_mode = tmi.fade_mode; + ti.fade_delay = tmi.fade_delay; + ti.post_delay = tmi.post_delay; + ti.auto_delay = tmi.auto_delay; return ti; } @@ -866,6 +909,8 @@ static void InitializeTitleControlsExt_AddTitleInfo(boolean is_image, title_controls[num_title_screens].local_nr = nr; title_controls[num_title_screens].sort_priority = sort_priority; + title_controls[num_title_screens].first = FALSE; /* will be set later */ + num_title_screens++; } @@ -908,6 +953,9 @@ static void InitializeTitleControls(boolean show_title_initial) /* sort title screens according to sort_priority and title number */ qsort(title_controls, num_title_screens, sizeof(struct TitleControlInfo), compareTitleControlInfo); + + /* mark first title screen */ + title_controls[0].first = TRUE; } static boolean visibleMenuPos(struct MenuPosInfo *pos) @@ -1162,6 +1210,49 @@ static boolean insideTextPosRect(struct TextPosInfo *rect, int x, int y) y >= rect_y && y < rect_y + rect->height); } +static boolean insidePreviewRect(struct PreviewInfo *preview, int x, int y) +{ + int rect_width = preview->xsize * preview->tile_size; + int rect_height = preview->ysize * preview->tile_size; + int rect_x = ALIGNED_XPOS(preview->x, rect_width, preview->align); + int rect_y = ALIGNED_YPOS(preview->y, rect_height, preview->valign); + + return (x >= rect_x && x < rect_x + rect_width && + 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]; @@ -1200,11 +1291,7 @@ static void drawCursorXY(int xpos, int ypos, int graphic) static void drawChooseTreeCursor(int ypos, boolean active) { - int last_game_status = game_status; /* save current game status */ - drawCursorExt(0, ypos, active, -1); - - game_status = last_game_status; /* restore current game status */ } void DrawHeadline() @@ -1214,14 +1301,6 @@ void DrawHeadline() setup.internal.program_copyright); } -int effectiveGameStatus() -{ - if (game_status == GAME_MODE_INFO && info_mode == INFO_MODE_TITLE) - return GAME_MODE_TITLE; - - return game_status; -} - void DrawTitleScreenImage(int nr, boolean initial) { int graphic = getTitleScreenGraphic(nr, initial); @@ -1270,13 +1349,20 @@ void DrawTitleScreenMessage(int nr, boolean initial) { char *filename = getLevelSetTitleMessageFilename(nr, initial); struct TitleMessageInfo *tmi = getTitleMessageInfo(nr, initial); - int last_game_status = game_status; /* save current game status */ if (filename == NULL) return; /* force TITLE font on title message screen */ - game_status = getTitleMessageGameMode(initial); + SetFontStatus(getTitleMessageGameMode(initial)); + + /* if chars *and* width set to "-1", automatically determine width */ + if (tmi->chars == -1 && tmi->width == -1) + tmi->width = viewport.window[game_status].width; + + /* if lines *and* height set to "-1", automatically determine height */ + if (tmi->lines == -1 && tmi->height == -1) + tmi->height = viewport.window[game_status].height; /* if chars set to "-1", automatically determine by text and font width */ if (tmi->chars == -1) @@ -1290,6 +1376,14 @@ void DrawTitleScreenMessage(int nr, boolean initial) else tmi->height = tmi->lines * getFontHeight(tmi->font); + /* if x set to "-1", automatically determine by width and alignment */ + if (tmi->x == -1) + tmi->x = -1 * ALIGNED_XPOS(0, tmi->width, tmi->align); + + /* if y set to "-1", automatically determine by height and alignment */ + if (tmi->y == -1) + tmi->y = -1 * ALIGNED_YPOS(0, tmi->height, tmi->valign); + SetDrawBackgroundMask(REDRAW_ALL); SetWindowBackgroundImage(getTitleBackground(nr, initial, FALSE)); @@ -1299,7 +1393,7 @@ void DrawTitleScreenMessage(int nr, boolean initial) filename, tmi->font, tmi->chars, -1, tmi->lines, 0, -1, tmi->autowrap, tmi->centered, tmi->parse_comments); - game_status = last_game_status; /* restore current game status */ + ResetFontStatus(); } void DrawTitleScreen() @@ -1307,8 +1401,6 @@ void DrawTitleScreen() KeyboardAutoRepeatOff(); HandleTitleScreen(0, 0, 0, 0, MB_MENU_INITIALIZE); - - StopAnimation(); } boolean CheckTitleScreen(boolean levelset_has_changed) @@ -1328,10 +1420,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); @@ -1340,10 +1433,11 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) /* do not fade out here -- function may continue and fade on editor screen */ UnmapAllGadgets(); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); + + ExpireSoundLoops(FALSE); KeyboardAutoRepeatOn(); - ActivateJoystick(); audio.sound_deactivated = FALSE; @@ -1352,7 +1446,10 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) /* needed if last screen was the playing screen, invoked from level editor */ if (level_editor_test_game) { - game_status = GAME_MODE_EDITOR; + CloseDoor(DOOR_CLOSE_ALL); + + SetGameStatus(GAME_MODE_EDITOR); + DrawLevelEd(); return; @@ -1377,27 +1474,27 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) /* needed if last screen (level choice) changed graphics, sounds or music */ ReloadCustomArtwork(0); + if (CheckTitleScreen(levelset_has_changed)) + { + SetGameStatus(GAME_MODE_TITLE); + + DrawTitleScreen(); + + return; + } + if (redraw_mask & REDRAW_ALL) fade_mask = REDRAW_ALL; + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + fade_mask = REDRAW_ALL; + FadeOut(fade_mask); /* needed if different viewport properties defined for menues */ ChangeViewportPropertiesIfNeeded(); - /* needed if last screen was the editor screen */ - UndrawSpecialEditorDoor(); - - SetDrawtoField(DRAW_BACKBUFFER); - - if (CheckTitleScreen(levelset_has_changed)) - { - game_status = GAME_MODE_TITLE; - - DrawTitleScreen(); - - return; - } + SetDrawtoField(DRAW_TO_BACKBUFFER); /* level_nr may have been set to value over handicap with level editor */ if (setup.handicap && level_nr > leveldir_current->handicap_level) @@ -1406,14 +1503,18 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) LoadLevel(level_nr); LoadScore(level_nr); + SaveLevelSetup_SeriesInfo(); + // 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) RedrawGlobalBorder(); +#endif ClearField(); @@ -1429,8 +1530,7 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) LoadTape(level_nr); DrawCompleteVideoDisplay(); - PlayMenuSound(); - PlayMenuMusic(); + PlayMenuSoundsAndMusic(); /* create gadgets for main menu screen */ FreeScreenGadgets(); @@ -1441,11 +1541,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(); @@ -1456,21 +1557,9 @@ void DrawMainMenuExt(int fade_mask, boolean do_fading) SetMouseCursor(CURSOR_DEFAULT); - InitAnimation(); - OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2); } -void DrawAndFadeInMainMenu(int fade_mask) -{ - DrawMainMenuExt(fade_mask, TRUE); -} - -void DrawMainMenu() -{ - DrawMainMenuExt(REDRAW_ALL, FALSE); -} - static void gotoTopLevelDir() { /* move upwards until inside (but not above) top level directory */ @@ -1507,11 +1596,7 @@ 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; - struct TitleFadingInfo fading_next; int sound, music; if (button == MB_MENU_INITIALIZE) @@ -1520,40 +1605,50 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) title_screen_nr = 0; tci = &title_controls[title_screen_nr]; + SetAnimStatus(getTitleAnimMode(tci)); + last_sound = SND_UNDEFINED; last_music = MUS_UNDEFINED; - if (game_status == GAME_MODE_INFO) + if (num_title_screens != 0) + { + FadeSetEnterScreen(); + + /* use individual title fading instead of global "enter screen" fading */ + fading = getTitleFading(tci); + } + + if (game_status_last_screen == GAME_MODE_INFO) { if (num_title_screens == 0) { + /* switch game mode from title screen mode back to info screen mode */ + SetGameStatus(GAME_MODE_INFO); + + /* store that last screen was info screen, not main menu screen */ + game_status_last_screen = GAME_MODE_INFO; + DrawInfoScreen_NotAvailable("Title screen information:", "No title screen for this level set."); - return; } - FadeSoundsAndMusic(); - - FadeOut(REDRAW_ALL); + FadeMenuSoundsAndMusic(); } + FadeOut(REDRAW_ALL); + + /* title screens may have different window size */ + ChangeViewportPropertiesIfNeeded(); + + /* only required to update logic for redrawing global border */ + ClearField(); + if (tci->is_image) DrawTitleScreenImage(tci->local_nr, tci->initial); else DrawTitleScreenMessage(tci->local_nr, tci->initial); - fading_default = (tci->initial ? title_initial_default : title_default); - - fading = fading_next = getTitleFading(tci); - - if (!(fading_last.fade_mode & FADE_TYPE_TRANSFORM) && - fading_next.fade_mode & FADE_TYPE_TRANSFORM) - { - fading.fade_mode = FADE_MODE_FADE; - fading.fade_delay = fading_default.fade_delay; - } - sound = getTitleSound(tci); music = getTitleMusic(tci); @@ -1569,8 +1664,6 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) FadeIn(REDRAW_ALL); - fading = fading_next; - DelayReached(&title_delay, 0); /* reset delay counter */ return; @@ -1582,33 +1675,38 @@ 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(); + SetGameStatus(GAME_MODE_INFO); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + + DrawInfoScreen(); return; } title_screen_nr++; - tci = &title_controls[title_screen_nr]; if (title_screen_nr < num_title_screens) { + tci = &title_controls[title_screen_nr]; + + SetAnimStatus(getTitleAnimMode(tci)); + sound = getTitleSound(tci); music = getTitleMusic(tci); - if (sound == SND_UNDEFINED || sound != last_sound) - FadeSounds(); - if (music == MUS_UNDEFINED || music != last_music) + if (last_sound != SND_UNDEFINED && sound != last_sound) + FadeSound(last_sound); + if (last_music != MUS_UNDEFINED && music != last_music) FadeMusic(); + fading = getTitleFading(tci); + FadeOut(REDRAW_ALL); if (tci->is_image) @@ -1616,8 +1714,6 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) else DrawTitleScreenMessage(tci->local_nr, tci->initial); - fading_next = getTitleFading(tci); - sound = getTitleSound(tci); music = getTitleMusic(tci); @@ -1629,20 +1725,13 @@ void HandleTitleScreen(int mx, int my, int dx, int dy, int button) last_sound = sound; last_music = music; - /* last screen already faded out, next screen has no animation */ - if (!(fading.fade_mode & FADE_TYPE_TRANSFORM) && - fading_next.fade_mode == FADE_MODE_NONE) - fading = fading_next; - FadeIn(REDRAW_ALL); - fading = fading_next; - DelayReached(&title_delay, 0); /* reset delay counter */ } else { - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); return_to_main_menu = TRUE; } @@ -1652,19 +1741,22 @@ 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) { - int fade_mask = (num_title_screens == 0 ? REDRAW_FIELD : REDRAW_ALL); + SetGameStatus(GAME_MODE_INFO); info_mode = INFO_MODE_MAIN; - DrawInfoScreenExt(fade_mask, use_fading_main_menu); + DrawInfoScreen(); } else /* default: return to main menu */ { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenuExt(REDRAW_ALL, use_fading_main_menu); + DrawMainMenu(); } } } @@ -1716,6 +1808,8 @@ void HandleMainMenu_SelectLevel(int step, int direction, int selected_level_nr) LoadTape(level_nr); DrawCompleteVideoDisplay(); + SaveLevelSetup_SeriesInfo(); + /* needed because DrawPreviewLevelInitial() takes some time */ BackToFront(); /* SyncDisplay(); */ @@ -1753,6 +1847,10 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } } + /* check if level preview was clicked */ + if (insidePreviewRect(&preview, mx - SX, my - SY)) + pos = MAIN_CONTROL_GAME; + // handle pressed/unpressed state for active/inactive menu buttons // (if pos != -1, "i" contains index position corresponding to "pos") if (button && @@ -1779,11 +1877,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) pos = choice + dy; } - if (pos == MAIN_CONTROL_LEVELS && dx != 0 && button) - { - HandleMainMenu_SelectLevel(1, (dx < 0 ? -1 : +1), NO_DIRECT_LEVEL_SELECT); - } - else if (pos == MAIN_CONTROL_FIRST_LEVEL && !button) + if (pos == MAIN_CONTROL_FIRST_LEVEL && !button) { HandleMainMenu_SelectLevel(MAX_LEVELS, -1, NO_DIRECT_LEVEL_SELECT); } @@ -1793,9 +1887,9 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_LEVEL_NUMBER && !button) { - game_status = GAME_MODE_LEVELNR; + CloseDoor(DOOR_CLOSE_2); - ChangeViewportPropertiesIfNeeded(); + SetGameStatus(GAME_MODE_LEVELNR); DrawChooseLevelNr(); } @@ -1812,6 +1906,12 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) choice = pos; } + else if (dx != 0) + { + if (choice != MAIN_CONTROL_INFO && + choice != MAIN_CONTROL_SETUP) + HandleMainMenu_SelectLevel(1, dx, NO_DIRECT_LEVEL_SELECT); + } } else { @@ -1819,7 +1919,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) if (pos == MAIN_CONTROL_NAME) { - game_status = GAME_MODE_PSEUDO_TYPENAME; + SetGameStatus(GAME_MODE_PSEUDO_TYPENAME); HandleTypeName(strlen(setup.player_name), 0); } @@ -1827,7 +1927,9 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) { if (leveldir_first) { - game_status = GAME_MODE_LEVELS; + CloseDoor(DOOR_CLOSE_2); + + SetGameStatus(GAME_MODE_LEVELS); SaveLevelSetup_LastSeries(); SaveLevelSetup_SeriesInfo(); @@ -1835,16 +1937,14 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) if (setup.internal.choose_from_top_leveldir) gotoTopLevelDir(); - ChangeViewportPropertiesIfNeeded(); - DrawChooseLevelSet(); } } else if (pos == MAIN_CONTROL_SCORES) { - game_status = GAME_MODE_SCORES; + CloseDoor(DOOR_CLOSE_2); - ChangeViewportPropertiesIfNeeded(); + SetGameStatus(GAME_MODE_SCORES); DrawHallOfFame(-1); } @@ -1856,7 +1956,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) CloseDoor(DOOR_CLOSE_2); - game_status = GAME_MODE_EDITOR; + SetGameStatus(GAME_MODE_EDITOR); FadeSetEnterScreen(); @@ -1864,10 +1964,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_INFO) { - game_status = GAME_MODE_INFO; - info_mode = INFO_MODE_MAIN; + CloseDoor(DOOR_CLOSE_2); - ChangeViewportPropertiesIfNeeded(); + SetGameStatus(GAME_MODE_INFO); + + info_mode = INFO_MODE_MAIN; DrawInfoScreen(); } @@ -1877,10 +1978,11 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) } else if (pos == MAIN_CONTROL_SETUP) { - game_status = GAME_MODE_SETUP; - setup_mode = SETUP_MODE_MAIN; + CloseDoor(DOOR_CLOSE_2); - ChangeViewportPropertiesIfNeeded(); + SetGameStatus(GAME_MODE_SETUP); + + setup_mode = SETUP_MODE_MAIN; DrawSetupScreen(); } @@ -1890,7 +1992,7 @@ void HandleMainMenu(int mx, int my, int dx, int dy, int button) SaveLevelSetup_SeriesInfo(); if (Request("Do you really want to quit?", REQ_ASK | REQ_STAY_CLOSED)) - game_status = GAME_MODE_QUIT; + SetGameStatus(GAME_MODE_QUIT); } } } @@ -1904,7 +2006,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() { @@ -1957,9 +2060,9 @@ static void execInfoLevelSet() static void execExitInfo() { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } static struct TokenInfo info_info_main[] = @@ -1977,107 +2080,246 @@ 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 (info_info[pos].type & ~TYPE_SKIP_ENTRY) - drawCursor(pos, active); + if (ti->type & ~TYPE_SKIP_ENTRY) + drawCursor(screen_pos, active); } -static void DrawInfoScreen_Main(int fade_mask, boolean do_fading) +static void DrawCursorAndText_Menu(int screen_pos, int menu_info_pos_raw, + boolean active) { - int i; - - UnmapAllGadgets(); - CloseDoor(DOOR_CLOSE_2); + DrawCursorAndText_Menu_Ext(menu_info, screen_pos, menu_info_pos_raw, active); +} - /* (needed after displaying title screens which disable auto repeat) */ - KeyboardAutoRepeatOn(); +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); +} - FadeSetLeaveScreen(); +static char *window_size_text; +static char *scaling_type_text; - FadeOut(fade_mask); +static void drawSetupValue(int, int); - if (fade_mask == REDRAW_ALL) - { - RedrawGlobalBorder(); +static void drawMenuInfoList(int first_entry, int num_page_entries, + int max_page_entries) +{ + int i; - OpenDoor(DOOR_CLOSE_1 | DOOR_CLOSE_2 | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); - } + if (first_entry + num_page_entries > max_page_entries) + first_entry = 0; - ClearField(); + clearMenuListArea(); - DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen"); + 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; - info_info = info_info_main; - num_info_info = 0; + /* 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 == &window_size_text && !video.window_scaling_available) || + (value_ptr == &scaling_type_text && !video.window_scaling_available)) + si->type |= TYPE_GHOSTED; - 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)) + if (si->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)) + else if (si->type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); - else if (info_info[i].type & ~TYPE_SKIP_ENTRY) + else if (si->type & ~TYPE_SKIP_ENTRY) initCursor(i, IMG_MENU_BUTTON); - DrawCursorAndText_Info(i, FALSE); + DrawCursorAndText_Menu(i, menu_info_pos, FALSE); - num_info_info++; + if (si->type & TYPE_VALUE && + menu_info == setup_info) + drawSetupValue(i, menu_info_pos); } +} - HandleInfoScreen_Main(0, 0, 0, 0, MB_MENU_INITIALIZE); +static void DrawInfoScreen_Main() +{ + int fade_mask = REDRAW_FIELD; + int i; - PlayMenuSound(); - PlayMenuMusic(); + if (redraw_mask & REDRAW_ALL) + fade_mask = REDRAW_ALL; - DrawMaskedBorder(fade_mask); + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + fade_mask = REDRAW_ALL; - FadeIn(fade_mask); + UnmapAllGadgets(); + FadeMenuSoundsAndMusic(); - InitAnimation(); -} + FreeScreenGadgets(); + CreateScreenGadgets(); -void HandleInfoScreen_Main(int mx, int my, int dx, int dy, int button) -{ - static int choice_store[MAX_INFO_MODES]; - int choice = choice_store[info_mode]; /* always starts with 0 */ - int x = 0; - int y = choice; + /* (needed after displaying title screens which disable auto repeat) */ + KeyboardAutoRepeatOn(); - if (button == MB_MENU_INITIALIZE) - { - /* advance to first valid menu entry */ - while (choice < num_info_info && - info_info[choice].type & TYPE_SKIP_ENTRY) - choice++; - choice_store[info_mode] = choice; + FadeSetLeaveScreen(); - DrawCursorAndText_Info(choice, TRUE); + FadeOut(fade_mask); + + /* needed if different viewport properties defined for info screen */ + ChangeViewportPropertiesIfNeeded(); + + SetMainBackgroundImage(IMG_BACKGROUND_INFO); + + ClearField(); + + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + + DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Info Screen"); + + info_info = info_info_main; + + // 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); + + PlayMenuSoundsAndMusic(); + + DrawMaskedBorder(fade_mask); + + FadeIn(fade_mask); +} + +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 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 - 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_page_entries && + menu_info[choice].type & TYPE_SKIP_ENTRY) + choice++; + + 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'! */ } } @@ -2089,62 +2331,244 @@ 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 */ { + /* 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; + + /* 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 (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) + 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 = choice + 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_MENU(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[mode] = first_entry + y; + } + else if (dx < 0) + { + PlaySound(SND_MENU_ITEM_SELECTING); + + for (i = 0; menu_info[i].type != 0; i++) + { + if (menu_info[i].type & TYPE_LEAVE_MENU) + { + void (*menu_callback_function)(void) = menu_info[i].value; + + FadeSetLeaveMenu(); + + menu_callback_function(); - choice = choice_store[info_mode] = y; + /* absolutely needed because function changes 'menu_info'! */ + break; + } + } + + return; } } - 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); +} + +static int getMenuFontSpacing(int spacing_height, int font_nr) +{ + int font_spacing = getFontHeight(font_nr) + EXTRA_SPACING(game_status); + + return (spacing_height < 0 ? ABS(spacing_height) * font_spacing : + spacing_height); +} + +static int getMenuTextSpacing(int spacing_height, int font_nr) +{ + return (getMenuFontSpacing(spacing_height, font_nr) + + EXTRA_SPACING(game_status)); +} + +static int getMenuTextStep(int spacing_height, int font_nr) +{ + return getFontHeight(font_nr) + getMenuTextSpacing(spacing_height, font_nr); +} + void DrawInfoScreen_NotAvailable(char *text_title, char *text_error) { + int font_title = MENU_INFO_FONT_TITLE; + int font_error = FONT_TEXT_2; + int font_foot = MENU_INFO_FONT_FOOT; + int spacing_title = menu.headline1_spacing_info[info_mode]; + int ystep_title = getMenuTextStep(spacing_title, font_title); int ystart1 = mSY - SY + 100; - int ystart2 = mSY - SY + 150; + int ystart2 = ystart1 + ystep_title; int ybottom = mSY - SY + SYSIZE - 20; SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO); @@ -2154,10 +2578,10 @@ void DrawInfoScreen_NotAvailable(char *text_title, char *text_error) ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, text_title); - DrawTextSCentered(ystart2, FONT_TEXT_2, text_error); + DrawTextSCentered(ystart1, font_title, text_title); + DrawTextSCentered(ystart2, font_error, text_error); - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for info menu"); FadeIn(REDRAW_FIELD); @@ -2167,6 +2591,8 @@ void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init) { static int infoscreen_step[MAX_INFO_ELEMENTS_ON_SCREEN]; static int infoscreen_frame[MAX_INFO_ELEMENTS_ON_SCREEN]; + int font_title = MENU_INFO_FONT_TITLE; + int font_foot = MENU_INFO_FONT_FOOT; int xstart = mSX + MENU_SCREEN_INFO_XSTART; int ystart1 = mSY - SY + MENU_SCREEN_INFO_YSTART1; int ystart2 = mSY + MENU_SCREEN_INFO_YSTART2; @@ -2186,9 +2612,9 @@ void DrawInfoScreen_HelpAnim(int start, int max_anims, boolean init) ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, "The Game Elements:"); + DrawTextSCentered(ystart1, font_title, "The Game Elements:"); - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for next page"); FrameCounter = 0; @@ -2295,10 +2721,12 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos) { int font_nr = FONT_INFO_ELEMENTS; int font_width = getFontWidth(font_nr); - int sx = mSX + MINI_TILEX + TILEX + MINI_TILEX; - int sy = mSY + 65 + 2 * 32 + 1; + int font_height = getFontHeight(font_nr); + int yoffset = (TILEX - 2 * font_height) / 2; + int xstart = mSX + MINI_TILEX + TILEX + MINI_TILEX; + int ystart = mSY + MENU_SCREEN_INFO_YSTART2 + yoffset; int ystep = TILEY + 4; - int pad_x = sx - SX; + int pad_x = xstart - SX; int max_chars_per_line = (SXSIZE - pad_x - MINI_TILEX) / font_width; int max_lines_per_text = 2; char *text = NULL; @@ -2319,15 +2747,17 @@ void DrawInfoScreen_HelpText(int element, int action, int direction, int ypos) text = "No description available"; if (strlen(text) <= max_chars_per_line) /* only one line of text */ - sy += getFontHeight(font_nr) / 2; + ystart += getFontHeight(font_nr) / 2; - DrawTextBuffer(sx, sy + ypos * ystep, text, font_nr, + DrawTextBuffer(xstart, ystart + ypos * ystep, text, font_nr, max_chars_per_line, -1, max_lines_per_text, 0, -1, TRUE, FALSE, FALSE); } void DrawInfoScreen_TitleScreen() { + SetGameStatus(GAME_MODE_TITLE); + DrawTitleScreen(); } @@ -2348,8 +2778,6 @@ void DrawInfoScreen_Elements() HandleInfoScreen_Elements(MB_MENU_INITIALIZE); FadeIn(REDRAW_FIELD); - - InitAnimation(); } void HandleInfoScreen_Elements(int button) @@ -2402,10 +2830,10 @@ void HandleInfoScreen_Elements(int button) if (page >= num_pages) { - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } @@ -2450,10 +2878,16 @@ void DrawInfoScreen_Music() void HandleInfoScreen_Music(int button) { static struct MusicFileInfo *list = NULL; - int ystart1 = mSY - SY + 100; - int ystart2 = mSY - SY + 150; + 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_info[info_mode]; + int spacing_head = menu.headline2_spacing_info[info_mode]; + int ystep_title = getMenuTextStep(spacing_title, font_title); + int ystep_head = getMenuTextStep(spacing_head, font_head); + int ystart = mSY - SY + 100; int ybottom = mSY - SY + SYSIZE - 20; - int dy = 30; if (button == MB_MENU_INITIALIZE) { @@ -2461,15 +2895,15 @@ void HandleInfoScreen_Music(int button) if (list == NULL) { - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, + DrawTextSCentered(ystart, font_title, "No music info for this level set."); - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for info menu"); return; @@ -2480,7 +2914,7 @@ void HandleInfoScreen_Music(int button) { PlaySound(SND_MENU_ITEM_SELECTING); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; DrawInfoScreen(); @@ -2489,8 +2923,6 @@ void HandleInfoScreen_Music(int button) } else if (button == MB_MENU_CHOICE || button == MB_MENU_INITIALIZE) { - int y = 0; - if (button != MB_MENU_INITIALIZE) { PlaySound(SND_MENU_ITEM_SELECTING); @@ -2501,15 +2933,15 @@ void HandleInfoScreen_Music(int button) if (list == NULL) { - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); if (list != music_file_info) FadeSetNextScreen(); @@ -2529,51 +2961,66 @@ void HandleInfoScreen_Music(int button) else PlaySound(sound); - DrawTextSCentered(ystart1, FONT_TEXT_1, "The Game Background Sounds:"); + DrawTextSCentered(ystart, font_title, "The Game Background Sounds:"); } else { PlayMusic(list->music); - DrawTextSCentered(ystart1, FONT_TEXT_1, "The Game Background Music:"); + DrawTextSCentered(ystart, font_title, "The Game Background Music:"); } + ystart += ystep_title; + if (!strEqual(list->title, UNKNOWN_NAME)) { if (!strEqual(list->title_header, UNKNOWN_NAME)) - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, list->title_header); + { + DrawTextSCentered(ystart, font_head, list->title_header); + ystart += ystep_head; + } - DrawTextFCentered(ystart2 + y++ * dy, FONT_TEXT_3, "\"%s\"", list->title); + DrawTextFCentered(ystart, font_text, "\"%s\"", list->title); + ystart += ystep_head; } if (!strEqual(list->artist, UNKNOWN_NAME)) { if (!strEqual(list->artist_header, UNKNOWN_NAME)) - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, list->artist_header); + DrawTextSCentered(ystart, font_head, list->artist_header); else - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, "by"); + DrawTextSCentered(ystart, font_head, "by"); + + ystart += ystep_head; - DrawTextFCentered(ystart2 + y++ * dy, FONT_TEXT_3, "%s", list->artist); + DrawTextFCentered(ystart, font_text, "%s", list->artist); + ystart += ystep_head; } if (!strEqual(list->album, UNKNOWN_NAME)) { if (!strEqual(list->album_header, UNKNOWN_NAME)) - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, list->album_header); + DrawTextSCentered(ystart, font_head, list->album_header); else - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, "from the album"); + DrawTextSCentered(ystart, font_head, "from the album"); - DrawTextFCentered(ystart2 + y++ * dy, FONT_TEXT_3, "\"%s\"", list->album); + ystart += ystep_head; + + DrawTextFCentered(ystart, font_text, "\"%s\"", list->album); + ystart += ystep_head; } if (!strEqual(list->year, UNKNOWN_NAME)) { if (!strEqual(list->year_header, UNKNOWN_NAME)) - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, list->year_header); + DrawTextSCentered(ystart, font_head, list->year_header); else - DrawTextSCentered(ystart2 + y++ * dy, FONT_TEXT_2, "from the year"); + DrawTextSCentered(ystart, font_head, "from the year"); + + ystart += ystep_head; - DrawTextFCentered(ystart2 + y++ * dy, FONT_TEXT_3, "%s", list->year); + DrawTextFCentered(ystart, font_text, "%s", list->year); + ystart += ystep_head; } DrawTextSCentered(ybottom, FONT_TEXT_4, @@ -2589,174 +3036,232 @@ void HandleInfoScreen_Music(int button) static void DrawInfoScreen_CreditsScreen(int screen_nr) { - int ystart1 = mSY - SY + 100; - int ystart2 = mSY - SY + 150; + 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_info[info_mode]; + int spacing_head = menu.headline2_spacing_info[info_mode]; + int spacing_para = menu.paragraph_spacing_info[info_mode]; + int spacing_line = menu.line_spacing_info[info_mode]; + int ystep_title = getMenuTextStep(spacing_title, font_title); + int ystep_head = getMenuTextStep(spacing_head, font_head); + int ystep_para = getMenuTextStep(spacing_para, font_text); + int ystep_line = getMenuTextStep(spacing_line, font_text); + int ystart = mSY - SY + 100; int ybottom = mSY - SY + SYSIZE - 20; - int ystep = 30; ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, "Credits:"); + DrawTextSCentered(ystart, font_title, "Credits:"); + ystart += ystep_title; if (screen_nr == 0) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Special thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Peter Liepa"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for creating"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "\"Boulder Dash\""); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "in the year"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "1984"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "published by"); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "First Star Software"); } else if (screen_nr == 1) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Special thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Klaus Heinz & Volker Wertich"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for creating"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "\"Emerald Mine\""); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "in the year"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "1987"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "published by"); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Kingsoft"); } else if (screen_nr == 2) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Special thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Michael Stopp & Philip Jespersen"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for creating"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "\"Supaplex\""); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "in the year"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "1991"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "published by"); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Digital Integration"); } else if (screen_nr == 3) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Special thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Hiroyuki Imabayashi"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for creating"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "\"Sokoban\""); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "in the year"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "1982"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "published by"); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Thinking Rabbit"); } else if (screen_nr == 4) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Special thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Alan Bond"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "and"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "J\xfcrgen Bonhagen"); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for the continuous creation"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_2, + ystart += ystep_line; + DrawTextSCentered(ystart, font_head, "of outstanding level sets"); } else if (screen_nr == 5) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Peter Elzner"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for ideas and inspiration by"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Diamond Caves"); + ystart += ystep_para; - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Thanks to"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Steffest"); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for ideas and inspiration by"); - DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "DX-Boulderdash"); } else if (screen_nr == 6) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "David Tritscher"); -#if 1 - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for the code base used for the"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_2, + ystart += ystep_line; + DrawTextSCentered(ystart, font_head, "native Emerald Mine engine"); -#else - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, - "for the new Emerald Mine engine"); -#endif } else if (screen_nr == 7) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Thanks to"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Guido Schulz"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for the initial DOS port"); + ystart += ystep_para; - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "Thanks to"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "Karl H\xf6rnell"); - DrawTextSCentered(ystart2 + 6 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "for some additional toons"); } else if (screen_nr == 8) { - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "And not to forget:"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "Many thanks to"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, "All those who contributed"); - DrawTextSCentered(ystart2 + 3 * ystep, FONT_TEXT_3, + ystart += ystep_line; + DrawTextSCentered(ystart, font_text, "levels to this game"); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_3, + ystart += ystep_line; + DrawTextSCentered(ystart, font_text, "since 1995"); } - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for next page"); } @@ -2764,7 +3269,7 @@ void DrawInfoScreen_Credits() { SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_CREDITS); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); FadeOut(REDRAW_FIELD); @@ -2805,10 +3310,10 @@ void HandleInfoScreen_Credits(int button) if (screen_nr >= num_screens) { - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); return; } @@ -2832,10 +3337,20 @@ void HandleInfoScreen_Credits(int button) void DrawInfoScreen_Program() { - int ystart1 = mSY - SY + 100; - int ystart2 = mSY - SY + 150; + 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_info[info_mode]; + int spacing_head = menu.headline2_spacing_info[info_mode]; + int spacing_para = menu.paragraph_spacing_info[info_mode]; + int spacing_line = menu.line_spacing_info[info_mode]; + int ystep_title = getMenuTextStep(spacing_title, font_title); + int ystep_head = getMenuTextStep(spacing_head, font_head); + int ystep_para = getMenuTextStep(spacing_para, font_text); + int ystep_line = getMenuTextStep(spacing_line, font_text); + int ystart = mSY - SY + 100; int ybottom = mSY - SY + SYSIZE - 20; - int ystep = 30; SetMainBackgroundImageIfDefined(IMG_BACKGROUND_INFO_PROGRAM); @@ -2844,26 +3359,36 @@ void DrawInfoScreen_Program() ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, "Program Information:"); + DrawTextSCentered(ystart, font_title, "Program Information:"); + ystart += ystep_title; - DrawTextSCentered(ystart2 + 0 * ystep, FONT_TEXT_2, + DrawTextSCentered(ystart, font_head, "This game is Freeware!"); - DrawTextSCentered(ystart2 + 1 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, "If you like it, send e-mail to:"); - DrawTextSCentered(ystart2 + 2 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, setup.internal.program_email); - DrawTextSCentered(ystart2 + 4 * ystep, FONT_TEXT_2, + ystart += ystep_para; + + DrawTextSCentered(ystart, font_head, "More information and levels:"); - DrawTextSCentered(ystart2 + 5 * ystep, FONT_TEXT_3, + ystart += ystep_head; + DrawTextSCentered(ystart, font_text, setup.internal.program_website); - DrawTextSCentered(ystart2 + 7 * ystep, FONT_TEXT_2, + ystart += ystep_para; + + DrawTextSCentered(ystart, font_head, "If you have created new levels,"); - DrawTextSCentered(ystart2 + 8 * ystep, FONT_TEXT_2, + ystart += ystep_line; + DrawTextSCentered(ystart, font_head, "send them to me to include them!"); - DrawTextSCentered(ystart2 + 9 * ystep, FONT_TEXT_2, + ystart += ystep_head; + DrawTextSCentered(ystart, font_head, ":-)"); - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for info menu"); FadeIn(REDRAW_FIELD); @@ -2884,10 +3409,10 @@ void HandleInfoScreen_Program(int button) { PlaySound(SND_MENU_ITEM_SELECTING); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -2897,12 +3422,20 @@ void HandleInfoScreen_Program(int button) void DrawInfoScreen_Version() { - int font_header = FONT_TEXT_3; - int font_text = FONT_TEXT_2; + 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_info[info_mode]; + int spacing_head = menu.headline2_spacing_info[info_mode]; + int spacing_para = menu.paragraph_spacing_info[info_mode]; + int spacing_line = menu.line_spacing_info[info_mode]; int xstep = getFontWidth(font_text); - int ystep = getFontHeight(font_text); - int ystart1 = mSY - SY + 100; - int ystart2 = mSY - SY + 150; + int ystep_title = getMenuTextStep(spacing_title, font_title); + int ystep_head = getMenuTextStep(spacing_head, font_head); + int ystep_para = getMenuTextStep(spacing_para, font_text); + int ystep_line = getMenuTextStep(spacing_line, font_text); + int ystart = mSY - SY + 100; int ybottom = mSY - SY + SYSIZE - 20; int xstart1 = mSX - SX + 2 * xstep; int xstart2 = mSX - SX + 18 * xstep; @@ -2924,31 +3457,46 @@ void DrawInfoScreen_Version() ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, "Version Information:"); + DrawTextSCentered(ystart, font_title, "Version Information:"); + ystart += ystep_title; + + DrawTextF(xstart1, ystart, font_head, "Name"); + DrawTextF(xstart2, ystart, font_text, getProgramTitleString()); + ystart += ystep_line; - DrawTextF(xstart1, ystart2, font_header, "Name"); - DrawTextF(xstart2, ystart2, font_text, getProgramTitleString()); + if (!strEqual(getProgramVersionString(), getProgramRealVersionString())) + { + DrawTextF(xstart1, ystart, font_head, "Version (fake)"); + DrawTextF(xstart2, ystart, font_text, getProgramVersionString()); + ystart += ystep_line; - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_header, "Version"); - DrawTextF(xstart2, ystart2, font_text, getProgramVersionString()); + DrawTextF(xstart1, ystart, font_head, "Version (real)"); + DrawTextF(xstart2, ystart, font_text, getProgramRealVersionString()); + ystart += ystep_line; + } + else + { + DrawTextF(xstart1, ystart, font_head, "Version"); + DrawTextF(xstart2, ystart, font_text, getProgramVersionString()); + ystart += ystep_line; + } - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_header, "Platform"); - DrawTextF(xstart2, ystart2, font_text, PLATFORM_STRING); + DrawTextF(xstart1, ystart, font_head, "Platform"); + DrawTextF(xstart2, ystart, font_text, PLATFORM_STRING); + ystart += ystep_line; - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_header, "Target"); - DrawTextF(xstart2, ystart2, font_text, TARGET_STRING); + DrawTextF(xstart1, ystart, font_head, "Target"); + DrawTextF(xstart2, ystart, font_text, TARGET_STRING); + ystart += ystep_line; - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_header, "Compile time"); - DrawTextF(xstart2, ystart2, font_text, getCompileDateString()); + DrawTextF(xstart1, ystart, font_head, "Source date"); + DrawTextF(xstart2, ystart, font_text, getSourceDateString()); + ystart += ystep_para; - ystart2 += 3 * ystep; - DrawTextF(xstart1, ystart2, font_header, "Library"); - DrawTextF(xstart2, ystart2, font_header, "compiled"); - DrawTextF(xstart3, ystart2, font_header, "linked"); + DrawTextF(xstart1, ystart, font_head, "Library"); + DrawTextF(xstart2, ystart, font_head, "compiled"); + DrawTextF(xstart3, ystart, font_head, "linked"); + ystart += ystep_head; SDL_VERSION(&sdl_version_compiled); #if defined(TARGET_SDL2) @@ -2958,63 +3506,63 @@ void DrawInfoScreen_Version() sdl_version_linked = SDL_Linked_Version(); #endif - ystart2 += 2 * ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL"); - DrawTextF(xstart2, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart1, ystart, font_text, "SDL"); + DrawTextF(xstart2, ystart, font_text, "%d.%d.%d", sdl_version_compiled.major, sdl_version_compiled.minor, sdl_version_compiled.patch); - DrawTextF(xstart3, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart3, ystart, font_text, "%d.%d.%d", sdl_version_linked->major, sdl_version_linked->minor, sdl_version_linked->patch); + ystart += ystep_line; SDL_IMAGE_VERSION(&sdl_version_compiled); sdl_version_linked = IMG_Linked_Version(); - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL_image"); - DrawTextF(xstart2, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart1, ystart, font_text, "SDL_image"); + DrawTextF(xstart2, ystart, font_text, "%d.%d.%d", sdl_version_compiled.major, sdl_version_compiled.minor, sdl_version_compiled.patch); - DrawTextF(xstart3, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart3, ystart, font_text, "%d.%d.%d", sdl_version_linked->major, sdl_version_linked->minor, sdl_version_linked->patch); + ystart += ystep_line; SDL_MIXER_VERSION(&sdl_version_compiled); sdl_version_linked = Mix_Linked_Version(); - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL_mixer"); - DrawTextF(xstart2, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart1, ystart, font_text, "SDL_mixer"); + DrawTextF(xstart2, ystart, font_text, "%d.%d.%d", sdl_version_compiled.major, sdl_version_compiled.minor, sdl_version_compiled.patch); - DrawTextF(xstart3, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart3, ystart, font_text, "%d.%d.%d", sdl_version_linked->major, sdl_version_linked->minor, sdl_version_linked->patch); + ystart += ystep_line; SDL_NET_VERSION(&sdl_version_compiled); sdl_version_linked = SDLNet_Linked_Version(); - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL_net"); - DrawTextF(xstart2, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart1, ystart, font_text, "SDL_net"); + DrawTextF(xstart2, ystart, font_text, "%d.%d.%d", sdl_version_compiled.major, sdl_version_compiled.minor, sdl_version_compiled.patch); - DrawTextF(xstart3, ystart2, font_text, "%d.%d.%d", + DrawTextF(xstart3, ystart, font_text, "%d.%d.%d", sdl_version_linked->major, sdl_version_linked->minor, sdl_version_linked->patch); + ystart += ystep_para; - ystart2 += 3 * ystep; - DrawTextF(xstart1, ystart2, font_header, "Driver"); - DrawTextF(xstart2, ystart2, font_header, "Requested"); - DrawTextF(xstart3, ystart2, font_header, "Used"); + DrawTextF(xstart1, ystart, font_head, "Driver"); + DrawTextF(xstart2, ystart, font_head, "Requested"); + DrawTextF(xstart3, ystart, font_head, "Used"); + ystart += ystep_head; #if defined(TARGET_SDL2) driver_name = getStringCopyNStatic(SDL_GetVideoDriver(0), driver_name_len); @@ -3022,10 +3570,10 @@ void DrawInfoScreen_Version() SDL_VideoDriverName(driver_name, driver_name_len); #endif - ystart2 += 2 * ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL_VideoDriver"); - DrawTextF(xstart2, ystart2, font_text, "%s", setup.system.sdl_videodriver); - DrawTextF(xstart3, ystart2, font_text, "%s", driver_name); + DrawTextF(xstart1, ystart, font_text, "SDL_VideoDriver"); + DrawTextF(xstart2, ystart, font_text, "%s", setup.system.sdl_videodriver); + DrawTextF(xstart3, ystart, font_text, "%s", driver_name); + ystart += ystep_line; #if defined(TARGET_SDL2) driver_name = getStringCopyNStatic(SDL_GetAudioDriver(0), driver_name_len); @@ -3033,12 +3581,11 @@ void DrawInfoScreen_Version() SDL_AudioDriverName(driver_name, driver_name_len); #endif - ystart2 += ystep; - DrawTextF(xstart1, ystart2, font_text, "SDL_AudioDriver"); - DrawTextF(xstart2, ystart2, font_text, "%s", setup.system.sdl_audiodriver); - DrawTextF(xstart3, ystart2, font_text, "%s", driver_name); + DrawTextF(xstart1, ystart, font_text, "SDL_AudioDriver"); + DrawTextF(xstart2, ystart, font_text, "%s", setup.system.sdl_audiodriver); + DrawTextF(xstart3, ystart, font_text, "%s", driver_name); - DrawTextSCentered(ybottom, FONT_TEXT_4, + DrawTextSCentered(ybottom, font_foot, "Press any key or button for info menu"); FadeIn(REDRAW_FIELD); @@ -3059,10 +3606,10 @@ void HandleInfoScreen_Version(int button) { PlaySound(SND_MENU_ITEM_SELECTING); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -3075,7 +3622,7 @@ void DrawInfoScreen_LevelSet() struct TitleMessageInfo *tmi = &readme; char *filename = getLevelSetInfoFilename(); char *title = "Level Set Information:"; - int ystart1 = mSY - SY + 100; + int ystart = mSY - SY + 100; int ybottom = mSY - SY + SYSIZE - 20; if (filename == NULL) @@ -3092,7 +3639,7 @@ void DrawInfoScreen_LevelSet() ClearField(); DrawHeadline(); - DrawTextSCentered(ystart1, FONT_TEXT_1, title); + DrawTextSCentered(ystart, FONT_TEXT_1, title); /* if x position set to "-1", automatically determine by playfield width */ if (tmi->x == -1) @@ -3147,10 +3694,10 @@ void HandleInfoScreen_LevelSet(int button) { PlaySound(SND_MENU_ITEM_SELECTING); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); info_mode = INFO_MODE_MAIN; - DrawAndFadeInInfoScreen(REDRAW_FIELD); + DrawInfoScreen(); } else { @@ -3158,10 +3705,8 @@ void HandleInfoScreen_LevelSet(int button) } } -static void DrawInfoScreenExt(int fade_mask, boolean do_fading) +static void DrawInfoScreen() { - SetMainBackgroundImage(IMG_BACKGROUND_INFO); - if (info_mode == INFO_MODE_TITLE) DrawInfoScreen_TitleScreen(); else if (info_mode == INFO_MODE_ELEMENTS) @@ -3177,25 +3722,12 @@ 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 && info_mode != INFO_MODE_MUSIC) - { - PlayMenuSound(); - PlayMenuMusic(); - } -} - -void DrawAndFadeInInfoScreen(int fade_mask) -{ - DrawInfoScreenExt(fade_mask, TRUE); -} - -void DrawInfoScreen() -{ - DrawInfoScreenExt(REDRAW_FIELD, FALSE); + PlayMenuSoundsAndMusic(); } void HandleInfoScreen(int mx, int my, int dx, int dy, int button) @@ -3246,9 +3778,7 @@ void HandleTypeName(int newxpos, Key key) xpos = newxpos; -#if defined(TARGET_SDL2) - SDL_StartTextInput(); -#endif + StartTextInput(startx, starty, pos->width, pos->height); } else if (is_valid_key_char && xpos < MAX_PLAYER_NAME_LEN) { @@ -3269,7 +3799,7 @@ void HandleTypeName(int newxpos, Key key) is_active = FALSE; - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); } else if (key == KSYM_Escape) { @@ -3277,7 +3807,7 @@ void HandleTypeName(int newxpos, Key key) is_active = FALSE; - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); } if (is_active) @@ -3295,9 +3825,7 @@ void HandleTypeName(int newxpos, Key key) DrawText(startx, starty, setup.player_name, font_nr); -#if defined(TARGET_SDL2) - SDL_StopTextInput(); -#endif + StopTextInput(); } } @@ -3308,13 +3836,16 @@ void HandleTypeName(int newxpos, Key key) static void DrawChooseTree(TreeInfo **ti_ptr) { - int fade_mask = (DrawingAreaChanged() ? REDRAW_ALL : REDRAW_FIELD); + int fade_mask = REDRAW_FIELD; + + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + fade_mask = REDRAW_ALL; if (strEqual((*ti_ptr)->subdir, STRING_TOP_DIRECTORY)) { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); return; } @@ -3324,50 +3855,26 @@ static void DrawChooseTree(TreeInfo **ti_ptr) FreeScreenGadgets(); CreateScreenGadgets(); - CloseDoor(DOOR_CLOSE_2); - FadeOut(fade_mask); - ClearField(); - - HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr); - MapScreenTreeGadgets(*ti_ptr); - - FadeIn(fade_mask); - - InitAnimation(); -} - -static void AdjustScrollbar(int id, int items_max, int items_visible, - int item_position) -{ - struct GadgetInfo *gi = screen_gadget[id]; + /* needed if different viewport properties defined for choosing level (set) */ + ChangeViewportPropertiesIfNeeded(); - if (item_position > items_max - items_visible) - item_position = items_max - items_visible; + if (game_status == GAME_MODE_LEVELNR) + SetMainBackgroundImage(IMG_BACKGROUND_LEVELNR); + else if (game_status == GAME_MODE_LEVELS) + SetMainBackgroundImage(IMG_BACKGROUND_LEVELS); - ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max, - GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible, - GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END); -} + ClearField(); -static void AdjustChooseTreeScrollbar(int id, int first_entry, TreeInfo *ti) -{ - AdjustScrollbar(id, numTreeInfoInGroup(ti), NUM_MENU_ENTRIES_ON_SCREEN, - first_entry); -} + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); -static void clearMenuListArea() -{ - int scrollbar_xpos = mSX + SC_SCROLLBAR_XPOS + menu.scrollbar_xoffset; + HandleChooseTree(0, 0, 0, 0, MB_MENU_INITIALIZE, ti_ptr); + MapScreenTreeGadgets(*ti_ptr); - /* correct scrollbar position if placed outside menu (playfield) area */ - if (scrollbar_xpos > SX + SC_SCROLLBAR_XPOS) - scrollbar_xpos = SX + SC_SCROLLBAR_XPOS; + DrawMaskedBorder(fade_mask); - /* 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); + FadeIn(fade_mask); } static void drawChooseTreeList(int first_entry, int num_page_entries, @@ -3379,7 +3886,6 @@ static void drawChooseTreeList(int first_entry, int num_page_entries, int yoffset_setup = 16; int yoffset = (ti->type == TREE_TYPE_LEVEL_DIR || ti->type == TREE_TYPE_LEVEL_NR ? yoffset_sets : yoffset_setup); - int last_game_status = game_status; /* save current game status */ title_string = ti->infotext; @@ -3419,8 +3925,6 @@ static void drawChooseTreeList(int first_entry, int num_page_entries, initCursor(i, IMG_MENU_BUTTON); } - game_status = last_game_status; /* restore current game status */ - redraw_mask |= REDRAW_FIELD; } @@ -3468,7 +3972,6 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, int step = (button == 1 ? 1 : button == 2 ? 5 : 10); int num_entries = numTreeInfoInGroup(ti); int num_page_entries; - int last_game_status = game_status; /* save current game status */ boolean position_set_by_scrollbar = (dx == 999); if (num_entries <= NUM_MENU_ENTRIES_ON_SCREEN) @@ -3476,8 +3979,6 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, else num_page_entries = NUM_MENU_ENTRIES_ON_SCREEN; - game_status = last_game_status; /* restore current game status */ - if (button == MB_MENU_INITIALIZE) { int num_entries = numTreeInfoInGroup(ti); @@ -3527,9 +4028,9 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, 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 || - setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE) + else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE || + setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE || + setup_mode == SETUP_MODE_CHOOSE_RENDERING) execSetupGraphics(); else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE || setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS || @@ -3551,9 +4052,9 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, HandleMainMenu_SelectLevel(0, 0, new_level_nr); } - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } return; @@ -3561,12 +4062,8 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, if (mx || my) /* mouse input */ { - int last_game_status = game_status; /* save current game status */ - x = (mx - mSX) / 32; y = (my - mSY) / 32 - MENU_SCREEN_START_YPOS; - - game_status = last_game_status; /* restore current game status */ } else if (dx || dy) /* keyboard or scrollbar/scrollbutton input */ { @@ -3675,6 +4172,30 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, ti->cl_cursor = y; } + else if (dx < 0) + { + 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_SNAPSHOT_MODE) + execSetupGame(); + else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE || + setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE || + setup_mode == SETUP_MODE_CHOOSE_RENDERING) + execSetupGraphics(); + else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE || + setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS || + setup_mode == SETUP_MODE_CHOOSE_VOLUME_MUSIC) + execSetupSound(); + else if (setup_mode == SETUP_MODE_CHOOSE_TOUCH_CONTROL || + setup_mode == SETUP_MODE_CHOOSE_MOVE_DISTANCE || + setup_mode == SETUP_MODE_CHOOSE_DROP_DISTANCE) + execSetupTouch(); + else + execSetupArtwork(); + } + } } else { @@ -3725,9 +4246,9 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, 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 || - setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE) + else if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE || + setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE || + setup_mode == SETUP_MODE_CHOOSE_RENDERING) execSetupGraphics(); else if (setup_mode == SETUP_MODE_CHOOSE_VOLUME_SIMPLE || setup_mode == SETUP_MODE_CHOOSE_VOLUME_LOOPS || @@ -3749,7 +4270,7 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, HandleMainMenu_SelectLevel(0, 0, new_level_nr); } - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); DrawMainMenu(); } @@ -3760,12 +4281,11 @@ static void HandleChooseTree(int mx, int my, int dx, int dy, int button, void DrawChooseLevelSet() { - SetMainBackgroundImage(IMG_BACKGROUND_LEVELS); + FadeMenuSoundsAndMusic(); DrawChooseTree(&leveldir_current); - PlayMenuSound(); - PlayMenuMusic(); + PlayMenuSoundsAndMusic(); } void HandleChooseLevelSet(int mx, int my, int dx, int dy, int button) @@ -3777,6 +4297,8 @@ void DrawChooseLevelNr() { int i; + FadeMenuSoundsAndMusic(); + if (level_number != NULL) { freeTreeInfo(level_number); @@ -3795,13 +4317,13 @@ void DrawChooseLevelNr() ti->node_top = &level_number; ti->sort_priority = 10000 + value; - ti->color = (level.no_valid_file ? FC_BLUE : + ti->color = (level.no_level_file ? FC_BLUE : LevelStats_getSolved(i) ? FC_GREEN : LevelStats_getPlayed(i) ? FC_YELLOW : FC_RED); - sprintf(identifier, "%d", value); - sprintf(name, "%03d: %s", value, - (level.no_valid_file ? "(no file)" : level.name)); + snprintf(identifier, sizeof(identifier), "%d", value); + snprintf(name, sizeof(name), "%03d: %s", value, + (level.no_level_file ? "(no file)" : level.name)); setString(&ti->identifier, identifier); setString(&ti->name, name); @@ -3821,12 +4343,9 @@ void DrawChooseLevelNr() if (level_number_current == NULL) level_number_current = level_number; - SetMainBackgroundImage(IMG_BACKGROUND_LEVELNR); - DrawChooseTree(&level_number_current); - PlayMenuSound(); - PlayMenuMusic(); + PlayMenuSoundsAndMusic(); } void HandleChooseLevelNr(int mx, int my, int dx, int dy, int button) @@ -3836,35 +4355,41 @@ void HandleChooseLevelNr(int mx, int my, int dx, int dy, int button) void DrawHallOfFame(int highlight_position) { - int fade_mask = (DrawingAreaChanged() ? REDRAW_ALL : REDRAW_FIELD); + int fade_mask = REDRAW_FIELD; + + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + fade_mask = REDRAW_ALL; UnmapAllGadgets(); - FadeSoundsAndMusic(); + FadeMenuSoundsAndMusic(); /* (this is needed when called from GameEnd() after winning a game) */ KeyboardAutoRepeatOn(); - ActivateJoystick(); /* (this is needed when called from GameEnd() after winning a game) */ SetDrawDeactivationMask(REDRAW_NONE); SetDrawBackgroundMask(REDRAW_FIELD); - CloseDoor(DOOR_CLOSE_ALL); - if (highlight_position < 0) LoadScore(level_nr); + else + SetAnimStatus(GAME_MODE_PSEUDO_SCORESNEW); FadeSetEnterScreen(); FadeOut(fade_mask); - InitAnimation(); + /* needed if different viewport properties defined for scores */ + ChangeViewportPropertiesIfNeeded(); + + PlayMenuSoundsAndMusic(); - PlayMenuSound(); - PlayMenuMusic(); + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); HandleHallOfFame(highlight_position, 0, 0, 0, MB_MENU_INITIALIZE); + DrawMaskedBorder(fade_mask); + FadeIn(fade_mask); } @@ -3887,9 +4412,10 @@ static void drawHallOfFameList(int first_entry, int highlight_position) int font_nr2 = (active ? FONT_TEXT_2_ACTIVE : FONT_TEXT_2); int font_nr3 = (active ? FONT_TEXT_3_ACTIVE : FONT_TEXT_3); int font_nr4 = (active ? FONT_TEXT_4_ACTIVE : FONT_TEXT_4); + int dxoff = getFontDrawOffsetX(font_nr1); int dx1 = 3 * getFontWidth(font_nr1); int dx2 = dx1 + getFontWidth(font_nr1); - int dx3 = SXSIZE - 2 * (mSX - SX) - 5 * getFontWidth(font_nr4); + int dx3 = SXSIZE - 2 * (mSX - SX + dxoff) - 5 * getFontWidth(font_nr4); int num_dots = (dx3 - dx2) / getFontWidth(font_nr3); int sy = mSY + 64 + i * 32; @@ -3954,7 +4480,7 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button) FadeSound(SND_BACKGROUND_SCORES); - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); DrawMainMenu(); } @@ -3964,9 +4490,9 @@ void HandleHallOfFame(int mx, int my, int dx, int dy, int button) FadeSound(SND_BACKGROUND_SCORES); - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawAndFadeInMainMenu(REDRAW_FIELD); + DrawMainMenu(); } if (game_status == GAME_MODE_SCORES) @@ -3982,9 +4508,9 @@ static struct TokenInfo *setup_info; static int num_setup_info; /* number of setup entries shown on screen */ static int max_setup_info; /* total number of setup entries in list */ -static char *screen_mode_text; static char *window_size_text; static char *scaling_type_text; +static char *rendering_mode_text; static char *scroll_delay_text; static char *snapshot_mode_text; static char *game_speed_text; @@ -4077,31 +4603,31 @@ static void execSetupGame_setScrollDelays() setString(&ti->identifier, identifier); setString(&ti->name, name); setString(&ti->name_sorting, name); - setString(&ti->infotext, "Scaling Type"); + setString(&ti->infotext, "Scroll Delay"); pushTreeInfo(&scroll_delays, ti); } - /* sort scaling type values to start with lowest scaling type value */ + /* sort scroll delay values to start with lowest scroll delay value */ sortTreeInfo(&scroll_delays); - /* set current scaling type value to configured scaling type value */ + /* set current scroll delay value to configured scroll delay value */ scroll_delay_current = getTreeInfoFromIdentifier(scroll_delays,i_to_a(setup.scroll_delay_value)); - /* if that fails, set current scaling type to reliable default value */ + /* if that fails, set current scroll delay to reliable default value */ if (scroll_delay_current == NULL) scroll_delay_current = getTreeInfoFromIdentifier(scroll_delays, i_to_a(STD_SCROLL_DELAY)); - /* if that also fails, set current scaling type to first available value */ + /* if that also fails, set current scroll delay to first available value */ if (scroll_delay_current == NULL) scroll_delay_current = scroll_delays; } setup.scroll_delay_value = atoi(scroll_delay_current->identifier); - /* needed for displaying scaling type text instead of identifier */ + /* needed for displaying scroll delay text instead of identifier */ scroll_delay_text = scroll_delay_current->name; } @@ -4329,82 +4855,70 @@ static void execSetupGraphics_setScalingTypes() scaling_type_text = scaling_type_current->name; } -static void execSetupGraphics_setScreenModes() +static void execSetupGraphics_setRenderingModes() { - // if (screen_modes == NULL && video.fullscreen_available) - if (screen_modes == NULL && video.fullscreen_modes != NULL) + if (rendering_modes == NULL) { int i; - for (i = 0; video.fullscreen_modes[i].width != -1; i++) + for (i = 0; rendering_modes_list[i].value != NULL; i++) { TreeInfo *ti = newTreeInfo_setDefaults(TREE_TYPE_UNDEFINED); char identifier[32], name[32]; - int x = video.fullscreen_modes[i].width; - int y = video.fullscreen_modes[i].height; - int xx, yy; + char *value = rendering_modes_list[i].value; + char *text = rendering_modes_list[i].text; - get_aspect_ratio_from_screen_mode(&video.fullscreen_modes[i], &xx, &yy); - - ti->node_top = &screen_modes; - ti->sort_priority = x * 10000 + y; + ti->node_top = &rendering_modes; + ti->sort_priority = i; - sprintf(identifier, "%dx%d", x, y); - sprintf(name, "%d x %d [%d:%d]", x, y, xx, yy); + sprintf(identifier, "%s", value); + sprintf(name, "%s", text); setString(&ti->identifier, identifier); setString(&ti->name, name); setString(&ti->name_sorting, name); - setString(&ti->infotext, "Fullscreen Mode"); + setString(&ti->infotext, "Special Rendering"); - pushTreeInfo(&screen_modes, ti); + pushTreeInfo(&rendering_modes, ti); } - /* sort fullscreen modes to start with lowest available screen resolution */ - sortTreeInfo(&screen_modes); + /* sort rendering mode values to start with lowest rendering mode value */ + sortTreeInfo(&rendering_modes); - /* set current screen mode for fullscreen mode to configured setup value */ - screen_mode_current = getTreeInfoFromIdentifier(screen_modes, - setup.fullscreen_mode); + /* set current rendering mode value to configured rendering mode value */ + rendering_mode_current = + getTreeInfoFromIdentifier(rendering_modes, setup.screen_rendering_mode); - /* if that fails, set current screen mode to reliable default value */ - if (screen_mode_current == NULL) - screen_mode_current = getTreeInfoFromIdentifier(screen_modes, - DEFAULT_FULLSCREEN_MODE); + /* if that fails, set current rendering mode to reliable default value */ + if (rendering_mode_current == NULL) + rendering_mode_current = + getTreeInfoFromIdentifier(rendering_modes, + STR_SPECIAL_RENDERING_DEFAULT); - /* if that also fails, set current screen mode to first available mode */ - if (screen_mode_current == NULL) - screen_mode_current = screen_modes; - - if (screen_mode_current == NULL) - video.fullscreen_available = FALSE; + /* if that also fails, set current rendering mode to first available one */ + if (rendering_mode_current == NULL) + rendering_mode_current = rendering_modes; } - // if (video.fullscreen_available) - if (screen_mode_current != NULL) - { - setup.fullscreen_mode = screen_mode_current->identifier; + setup.screen_rendering_mode = rendering_mode_current->identifier; - /* needed for displaying screen mode name instead of identifier */ - screen_mode_text = screen_mode_current->name; - } + /* needed for displaying rendering mode text instead of identifier */ + rendering_mode_text = rendering_mode_current->name; } static void execSetupGraphics() { + // update "setup.window_scaling_percent" from list selection + // (in this case, window scaling was changed on setup screen) if (setup_mode == SETUP_MODE_CHOOSE_WINDOW_SIZE) - { - // update "setup.window_scaling_percent" from list selection execSetupGraphics_setWindowSizes(FALSE); - } - else - { - // update list selection from "setup.window_scaling_percent" - execSetupGraphics_setWindowSizes(TRUE); - } + + // update list selection from "setup.window_scaling_percent" + // (window scaling may have changed by resizing the window) + execSetupGraphics_setWindowSizes(TRUE); execSetupGraphics_setScalingTypes(); - execSetupGraphics_setScreenModes(); + execSetupGraphics_setRenderingModes(); setup_mode = SETUP_MODE_GRAPHICS; @@ -4417,11 +4931,13 @@ static void execSetupGraphics() // window scaling quality may have changed at this point if (!strEqual(setup.window_scaling_quality, video.window_scaling_quality)) SDLSetWindowScalingQuality(setup.window_scaling_quality); + + // screen rendering mode may have changed at this point + SDLSetScreenRenderingMode(setup.screen_rendering_mode); #endif } -#if !defined(PLATFORM_ANDROID) -#if defined(TARGET_SDL2) +#if defined(TARGET_SDL2) && !defined(PLATFORM_ANDROID) static void execSetupChooseWindowSize() { setup_mode = SETUP_MODE_CHOOSE_WINDOW_SIZE; @@ -4435,18 +4951,14 @@ static void execSetupChooseScalingType() DrawSetupScreen(); } -#else -static void execSetupChooseScreenMode() -{ - if (!video.fullscreen_available) - return; - setup_mode = SETUP_MODE_CHOOSE_SCREEN_MODE; +static void execSetupChooseRenderingMode() +{ + setup_mode = SETUP_MODE_CHOOSE_RENDERING; DrawSetupScreen(); } #endif -#endif static void execSetupChooseVolumeSimple() { @@ -4901,14 +5413,12 @@ static void execSetupChooseMusic() DrawSetupScreen(); } -#if !defined(PLATFORM_ANDROID) static void execSetupInput() { setup_mode = SETUP_MODE_INPUT; DrawSetupScreen(); } -#endif static void execSetupShortcuts() { @@ -4954,9 +5464,9 @@ static void execSetupShortcuts5() static void execExitSetup() { - game_status = GAME_MODE_MAIN; + SetGameStatus(GAME_MODE_MAIN); - DrawMainMenuExt(REDRAW_FIELD, FALSE); + DrawMainMenu(); } static void execSaveAndExitSetup() @@ -4972,12 +5482,8 @@ static struct TokenInfo setup_info_main[] = { TYPE_ENTER_MENU, execSetupGraphics, "Graphics" }, { TYPE_ENTER_MENU, execSetupSound, "Sound & Music" }, { TYPE_ENTER_MENU, execSetupArtwork, "Custom Artwork" }, -#if !defined(PLATFORM_ANDROID) { TYPE_ENTER_MENU, execSetupInput, "Input Devices" }, { TYPE_ENTER_MENU, execSetupTouch, "Touch Controls" }, -#else - { TYPE_ENTER_MENU, execSetupTouch, "Touch Controls" }, -#endif { TYPE_ENTER_MENU, execSetupShortcuts, "Key Shortcuts" }, { TYPE_EMPTY, NULL, "" }, { TYPE_LEAVE_MENU, execExitSetup, "Exit" }, @@ -4990,9 +5496,10 @@ static struct TokenInfo setup_info_game[] = { { TYPE_SWITCH, &setup.team_mode, "Team-Mode (Multi-Player):" }, { TYPE_YES_NO, &setup.input_on_focus, "Only Move Focussed Player:" }, + { TYPE_SWITCH, &setup.time_limit, "Time Limit:" }, { TYPE_SWITCH, &setup.handicap, "Handicap:" }, { TYPE_SWITCH, &setup.skip_levels, "Skip Unsolved Levels:" }, - { TYPE_SWITCH, &setup.time_limit, "Time Limit:" }, + { TYPE_SWITCH, &setup.increment_levels,"Increment Solved Levels:" }, { TYPE_SWITCH, &setup.autorecord, "Auto-Record Tapes:" }, { TYPE_ENTER_LIST, execSetupChooseGameSpeed, "Game Speed:" }, { TYPE_STRING, &game_speed_text, "" }, @@ -5002,6 +5509,7 @@ static struct TokenInfo setup_info_game[] = #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" }, @@ -5019,9 +5527,10 @@ static struct TokenInfo setup_info_editor[] = { TYPE_SWITCH, &setup.editor.el_supaplex, "Supaplex:" }, { TYPE_SWITCH, &setup.editor.el_diamond_caves, "Diamond Caves II:" }, { TYPE_SWITCH, &setup.editor.el_dx_boulderdash,"DX-Boulderdash:" }, -#endif { TYPE_SWITCH, &setup.editor.el_chars, "Text Characters:" }, { TYPE_SWITCH, &setup.editor.el_steel_chars, "Text Characters (Steel):" }, +#endif + { TYPE_SWITCH, &setup.editor.el_classic, "Classic Elements:" }, { TYPE_SWITCH, &setup.editor.el_custom, "Custom & Group Elements:" }, #if 0 { TYPE_SWITCH, &setup.editor.el_headlines, "Headlines:" }, @@ -5043,17 +5552,14 @@ static struct TokenInfo setup_info_editor[] = static struct TokenInfo setup_info_graphics[] = { -#if !defined(PLATFORM_ANDROID) +#if defined(TARGET_SDL2) && !defined(PLATFORM_ANDROID) { TYPE_SWITCH, &setup.fullscreen, "Fullscreen:" }, -#if defined(TARGET_SDL2) { TYPE_ENTER_LIST, execSetupChooseWindowSize, "Window Scaling:" }, { TYPE_STRING, &window_size_text, "" }, { TYPE_ENTER_LIST, execSetupChooseScalingType, "Anti-Aliasing:" }, { TYPE_STRING, &scaling_type_text, "" }, -#else - { TYPE_ENTER_LIST, execSetupChooseScreenMode, "Fullscreen Mode:" }, - { TYPE_STRING, &screen_mode_text, "" }, -#endif + { TYPE_ENTER_LIST, execSetupChooseRenderingMode, "Special Rendering:" }, + { TYPE_STRING, &rendering_mode_text, "" }, #endif #if 0 { TYPE_ENTER_LIST, execSetupChooseScrollDelay, "Scroll Delay:" }, @@ -5063,7 +5569,7 @@ static struct TokenInfo setup_info_graphics[] = { TYPE_SWITCH, &setup.quick_switch, "Quick Player Focus Switch:" }, { TYPE_SWITCH, &setup.quick_doors, "Quick Menu Doors:" }, { TYPE_SWITCH, &setup.show_titlescreen,"Show Title Screens:" }, - { TYPE_SWITCH, &setup.toons, "Show Toons:" }, + { TYPE_SWITCH, &setup.toons, "Show Menu Animations:" }, { TYPE_ECS_AGA, &setup.prefer_aga_graphics,"EMC graphics preference:" }, { TYPE_SWITCH, &setup.sp_show_border_elements,"Supaplex Border Elements:" }, { TYPE_SWITCH, &setup.small_game_graphics, "Small Game Graphics:" }, @@ -5113,7 +5619,7 @@ static struct TokenInfo setup_info_input[] = { { TYPE_SWITCH, NULL, "Player:" }, { TYPE_SWITCH, NULL, "Device:" }, - { TYPE_ENTER_MENU, NULL, "" }, + { TYPE_SWITCH, NULL, "" }, { TYPE_EMPTY, NULL, "" }, { TYPE_EMPTY, NULL, "" }, { TYPE_EMPTY, NULL, "" }, @@ -5130,6 +5636,16 @@ static struct TokenInfo setup_info_input[] = }; static struct TokenInfo setup_info_touch[] = +{ + { TYPE_ENTER_LIST, execSetupChooseTouchControls, "Touch Control Type:" }, + { TYPE_STRING, &touch_controls_text, "" }, + { TYPE_EMPTY, NULL, "" }, + { TYPE_LEAVE_MENU, execSetupMain, "Back" }, + + { 0, NULL, NULL } +}; + +static struct TokenInfo setup_info_touch_wipe_gestures[] = { { TYPE_ENTER_LIST, execSetupChooseTouchControls, "Touch Control Type:" }, { TYPE_STRING, &touch_controls_text, "" }, @@ -5249,12 +5765,10 @@ static Key getSetupKey() while (!got_key_event) { - if (PendingEvent()) /* got event */ - { - Event event; - - NextEvent(&event); + Event event; + if (NextValidEvent(&event)) + { switch (event.type) { case EVENT_KEYPRESS: @@ -5279,33 +5793,17 @@ static Key getSetupKey() } } - DoAnimation(); BackToFront(); - - /* don't eat all CPU time */ - Delay(10); } 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) + if (type & TYPE_GHOSTED) + return FONT_OPTION_OFF; + else if (type & TYPE_KEY) return (type & TYPE_QUERY ? FONT_INPUT_1_ACTIVE : FONT_VALUE_1); else if (type & TYPE_STRING) return FONT_VALUE_2; @@ -5320,20 +5818,29 @@ static int getSetupValueFont(int type, void *value) return FONT_VALUE_1; } +static int getSetupValueFontNarrow(int type, int font_nr) +{ + return (font_nr == FONT_VALUE_1 ? FONT_VALUE_NARROW : + font_nr == FONT_OPTION_ON ? FONT_OPTION_ON_NARROW : + font_nr == FONT_OPTION_OFF ? FONT_OPTION_OFF_NARROW : + font_nr); +} + static void drawSetupValue(int screen_pos, int setup_info_pos_raw) { int si_pos = (setup_info_pos_raw < 0 ? screen_pos : setup_info_pos_raw); struct TokenInfo *si = &setup_info[si_pos]; boolean font_draw_xoffset_modified = FALSE; + boolean scrollbar_needed = (num_setup_info < max_setup_info); int font_draw_xoffset_old = -1; - int xoffset = (num_setup_info < max_setup_info ? -1 : 0); + int xoffset = (scrollbar_needed ? -1 : 0); int menu_screen_value_xpos = MENU_SCREEN_VALUE_XPOS + xoffset; int menu_screen_max_xpos = MENU_SCREEN_MAX_XPOS + xoffset; int xpos = menu_screen_value_xpos; int ypos = MENU_SCREEN_START_YPOS + screen_pos; int startx = mSX + xpos * 32; int starty = mSY + ypos * 32; - int font_nr, font_width; + int font_nr, font_nr_default, font_width_default; int type = si->type; void *value = si->value; char *value_string = getSetupValue(type, value); @@ -5365,8 +5872,29 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw) startx = mSX + xpos * 32; starty = mSY + ypos * 32; - font_nr = getSetupValueFont(type, value); - font_width = getFontWidth(font_nr); + font_nr_default = getSetupValueFont(type, value); + font_width_default = getFontWidth(font_nr_default); + + font_nr = font_nr_default; + + // special check if right-side setup values moved left due to scrollbar + if (scrollbar_needed && xpos > MENU_SCREEN_START_XPOS) + { + int max_menu_text_length = 26; // maximum text length for classic menu + int font_xoffset = getFontBitmapInfo(font_nr)->draw_xoffset; + int text_startx = mSX + MENU_SCREEN_START_XPOS * 32; + 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 * getFontWidth(text_font_nr); + + if (startx + font_xoffset < text_startx + text_width + text_font_xoffset) + { + xpos += 1; + startx = mSX + xpos * 32; + + font_nr = getSetupValueFontNarrow(type, font_nr); + } + } /* downward compatibility correction for Juergen Bonhagen's menu settings */ if (setup_mode != SETUP_MODE_INPUT) @@ -5378,7 +5906,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; @@ -5407,7 +5935,7 @@ static void drawSetupValue(int screen_pos, int setup_info_pos_raw) } for (i = 0; i <= menu_screen_max_xpos - xpos; i++) - DrawText(startx + i * font_width, starty, " ", font_nr); + DrawText(startx + i * font_width_default, starty, " ", font_nr_default); DrawText(startx, starty, value_string, font_nr); @@ -5453,94 +5981,58 @@ 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) +static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *setup_info_orig) { + static struct TokenInfo *setup_info_hide = NULL; + int list_size = 0; + int list_pos = 0; 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; - - clearMenuListArea(); - - 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; + /* determine maximum list size of target list */ + while (setup_info_orig[list_size++].type != 0); - 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); + /* free, allocate and clear memory for target list */ + checked_free(setup_info_hide); + setup_info_hide = checked_calloc(list_size * sizeof(struct TokenInfo)); - DrawCursorAndText_Setup(i, setup_info_pos, FALSE); + /* copy setup info list without setup entries marked as hidden */ + for (i = 0; setup_info_orig[i].type != 0; i++) + if (!hideSetupEntry(setup_info_orig[i].value)) + setup_info_hide[list_pos++] = setup_info_orig[i]; - if (si->type & TYPE_VALUE) - drawSetupValue(i, setup_info_pos); - } + return setup_info_hide; } static void DrawSetupScreen_Generic() { - int fade_mask = (DrawingAreaChanged() ? REDRAW_ALL : REDRAW_FIELD); + int fade_mask = REDRAW_FIELD; boolean redraw_all = FALSE; char *title_string = NULL; int i; + if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged()) + fade_mask = REDRAW_ALL; + UnmapAllGadgets(); + FadeMenuSoundsAndMusic(); FreeScreenGadgets(); CreateScreenGadgets(); - CloseDoor(DOOR_CLOSE_2); - if (redraw_mask & REDRAW_ALL) redraw_all = TRUE; FadeOut(fade_mask); + /* needed if different viewport properties defined for setup screen */ + ChangeViewportPropertiesIfNeeded(); + + SetMainBackgroundImage(IMG_BACKGROUND_SETUP); + ClearField(); + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + if (setup_mode == SETUP_MODE_MAIN) { setup_info = setup_info_main; @@ -5575,6 +6067,9 @@ static void DrawSetupScreen_Generic() { setup_info = setup_info_touch; title_string = "Setup Touch Ctrls"; + + if (strEqual(setup.touch.control_type, TOUCH_CONTROL_WIPE_GESTURES)) + setup_info = setup_info_touch_wipe_gestures; } else if (setup_mode == SETUP_MODE_SHORTCUTS) { @@ -5607,6 +6102,9 @@ static void DrawSetupScreen_Generic() title_string = "Setup Shortcuts"; } + /* use modified setup info without setup entries marked as hidden */ + setup_info = getSetupInfoFinal(setup_info); + DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, title_string); // determine maximal number of setup entries that can be displayed on screen @@ -5626,296 +6124,41 @@ static void DrawSetupScreen_Generic() if (redraw_all) redraw_mask = fade_mask = REDRAW_ALL; - FadeIn(fade_mask); + DrawMaskedBorder(fade_mask); - InitAnimation(); + FadeIn(fade_mask); } 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; + menu_info = setup_info; - num_page_entries = MIN(max_setup_info, NUM_MENU_ENTRIES_ON_SCREEN); - - 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); + HandleMenuScreen(mx, my, dx, dy, button, + setup_mode, num_setup_info, max_setup_info); +} - drawSetupInfoList(setup_info, first_entry, NUM_MENU_ENTRIES_ON_SCREEN); +void DrawSetupScreen_Input() +{ + int i; - if (choice < first_entry) - { - choice = first_entry; + FadeOut(REDRAW_FIELD); - 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; + ClearField(); - if (setup_info[choice].type & TYPE_SKIP_ENTRY) - choice--; - } + setup_info = setup_info_input; - choice_store[setup_mode] = choice; + DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Setup Input"); - DrawCursorAndText_Setup(choice - first_entry, choice, TRUE); + for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++) + { + if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST)) + initCursor(i, IMG_MENU_BUTTON_ENTER_MENU); + else if (setup_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) + initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); + else if (setup_info[i].type & ~TYPE_SKIP_ENTRY) + initCursor(i, IMG_MENU_BUTTON); - 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_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_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_MENU(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); - } - } - } -} - -void DrawSetupScreen_Input() -{ - int i; - - FadeOut(REDRAW_FIELD); - - ClearField(); - - setup_info = setup_info_input; - - DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Setup Input"); - - DrawTextSCentered(SYSIZE - 20, FONT_TITLE_2, - "Joysticks deactivated on this screen"); - - for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++) - { - if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST)) - initCursor(i, IMG_MENU_BUTTON_ENTER_MENU); - else if (setup_info[i].type & (TYPE_LEAVE_MENU|TYPE_LEAVE_LIST)) - initCursor(i, IMG_MENU_BUTTON_LEAVE_MENU); - else if (setup_info[i].type & ~TYPE_SKIP_ENTRY) - initCursor(i, IMG_MENU_BUTTON); - - DrawCursorAndText_Setup(i, -1, FALSE); + DrawCursorAndText_Setup(i, -1, FALSE); } /* create gadgets for setup input menu screen */ @@ -5928,8 +6171,6 @@ void DrawSetupScreen_Input() HandleSetupScreen_Input(0, 0, 0, 0, MB_MENU_INITIALIZE); FadeIn(REDRAW_FIELD); - - InitAnimation(); } static void setJoystickDeviceToNr(char *device_name, int device_nr) @@ -5963,12 +6204,12 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active) char *text; } custom[] = { - { &custom_key.left, "Joystick Left" }, - { &custom_key.right, "Joystick Right" }, - { &custom_key.up, "Joystick Up" }, - { &custom_key.down, "Joystick Down" }, - { &custom_key.snap, "Button 1" }, - { &custom_key.drop, "Button 2" } + { &custom_key.left, "Axis/Pad Left" }, + { &custom_key.right, "Axis/Pad Right" }, + { &custom_key.up, "Axis/Pad Up" }, + { &custom_key.down, "Axis/Pad Down" }, + { &custom_key.snap, "Button 1/A/X" }, + { &custom_key.drop, "Button 2/B/Y" } }; static char *joystick_name[MAX_PLAYERS] = { @@ -5979,8 +6220,6 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active) }; int text_font_nr = (active ? FONT_MENU_1_ACTIVE : FONT_MENU_1); - InitJoysticks(); - custom_key = setup.input[player_nr].key; DrawText(mSX + 11 * 32, mSY + 2 * 32, int2str(player_nr + 1, 1), @@ -5994,11 +6233,13 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active) if (setup.input[player_nr].use_joystick) { char *device_name = setup.input[player_nr].joy.device_name; - char *text = joystick_name[getJoystickNrFromDeviceName(device_name)]; - int font_nr = (joystick.fd[player_nr] < 0 ? FONT_VALUE_OLD : FONT_VALUE_1); + int joystick_nr = getJoystickNrFromDeviceName(device_name); + boolean joystick_active = CheckJoystickOpened(joystick_nr); + char *text = joystick_name[joystick_nr]; + int font_nr = (joystick_active ? FONT_VALUE_1 : FONT_VALUE_OLD); DrawText(mSX + 8 * 32, mSY + 3 * 32, text, font_nr); - DrawText(mSX + 32, mSY + 4 * 32, "Calibrate", text_font_nr); + DrawText(mSX + 32, mSY + 4 * 32, "Configure", text_font_nr); } else { @@ -6091,7 +6332,6 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button) if (dx && choice == 0) x = (dx < 0 ? 10 : 12); else if ((dx && choice == 1) || - (dx == +1 && choice == 2) || (dx == -1 && choice == pos_end)) button = MB_MENU_CHOICE; else if (dy) @@ -6150,10 +6390,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button) else if (y == 2) { if (setup.input[input_player_nr].use_joystick) - { - InitJoysticks(); - CalibrateJoystick(input_player_nr); - } + ConfigureJoystick(input_player_nr); else CustomizeKeyboard(input_player_nr); } @@ -6210,16 +6447,12 @@ void CustomizeKeyboard(int player_nr) FadeIn(REDRAW_FIELD); - InitAnimation(); - while (!finished) { - if (PendingEvent()) /* got event */ - { - Event event; - - NextEvent(&event); + Event event; + if (NextValidEvent(&event)) + { switch (event.type) { case EVENT_KEYPRESS: @@ -6293,211 +6526,439 @@ void CustomizeKeyboard(int player_nr) } } - DoAnimation(); BackToFront(); - - /* don't eat all CPU time */ - Delay(10); } /* write new key bindings back to player setup */ setup.input[player_nr].key = custom_key; - StopAnimation(); DrawSetupScreen_Input(); } -static boolean CalibrateJoystickMain(int player_nr) -{ - int new_joystick_xleft = JOYSTICK_XMIDDLE; - int new_joystick_xright = JOYSTICK_XMIDDLE; - int new_joystick_yupper = JOYSTICK_YMIDDLE; - int new_joystick_ylower = JOYSTICK_YMIDDLE; - int new_joystick_xmiddle, new_joystick_ymiddle; +/* game controller mapping generator by Gabriel Jacobo */ - int joystick_fd = joystick.fd[player_nr]; - int x, y, last_x, last_y, xpos = 8, ypos = 3; - boolean check[3][3]; - int check_remaining = 3 * 3; - int joy_x, joy_y; - int joy_value; - int result = -1; +#define MARKER_BUTTON 1 +#define MARKER_AXIS_X 2 +#define MARKER_AXIS_Y 3 - if (joystick.status == JOYSTICK_NOT_AVAILABLE) - return FALSE; +static boolean ConfigureJoystickMapButtonsAndAxes(SDL_Joystick *joystick) +{ +#if defined(TARGET_SDL2) + static boolean bitmaps_initialized = FALSE; + boolean screen_initialized = FALSE; + static Bitmap *controller, *button, *axis_x, *axis_y; + char *name; + boolean success = TRUE; + boolean done = FALSE, next = FALSE; + Event event; + int alpha = 200, alpha_step = -1; + int alpha_ticks = 0; + char mapping[4096], temp[4096]; + int font_name = MENU_SETUP_FONT_TITLE; + int font_info = MENU_SETUP_FONT_TEXT; + int spacing_name = menu.line_spacing_setup[SETUP_MODE_INPUT]; + int spacing_line = menu.line_spacing_setup[SETUP_MODE_INPUT]; + int spacing_para = menu.paragraph_spacing_setup[SETUP_MODE_INPUT]; + int ystep_name = getMenuTextStep(spacing_name, font_name); + int ystep_line = getMenuTextStep(spacing_line, font_info); + int ystep_para = getMenuTextStep(spacing_para, font_info); + int i, j; - if (joystick_fd < 0 || !setup.input[player_nr].use_joystick) - return FALSE; + struct + { + int x, y; + int marker; + char *field; + int axis, button, hat, hat_value; + char mapping[4096]; + } + *step, *prev_step, steps[] = + { + { 356, 155, MARKER_BUTTON, "a", }, + { 396, 122, MARKER_BUTTON, "b", }, + { 320, 125, MARKER_BUTTON, "x", }, + { 358, 95, MARKER_BUTTON, "y", }, + { 162, 125, MARKER_BUTTON, "back", }, + { 216, 125, MARKER_BUTTON, "guide", }, + { 271, 125, MARKER_BUTTON, "start", }, + { 110, 200, MARKER_BUTTON, "dpleft", }, + { 146, 228, MARKER_BUTTON, "dpdown", }, + { 178, 200, MARKER_BUTTON, "dpright", }, + { 146, 172, MARKER_BUTTON, "dpup", }, + { 50, 40, MARKER_BUTTON, "leftshoulder", }, + { 88, -10, MARKER_AXIS_Y, "lefttrigger", }, + { 382, 40, MARKER_BUTTON, "rightshoulder", }, + { 346, -10, MARKER_AXIS_Y, "righttrigger", }, + { 73, 141, MARKER_BUTTON, "leftstick", }, + { 282, 210, MARKER_BUTTON, "rightstick", }, + { 73, 141, MARKER_AXIS_X, "leftx", }, + { 73, 141, MARKER_AXIS_Y, "lefty", }, + { 282, 210, MARKER_AXIS_X, "rightx", }, + { 282, 210, MARKER_AXIS_Y, "righty", }, + }; - FadeSetEnterMenu(); - FadeOut(REDRAW_FIELD); + unsigned int event_frame_delay = 0; + unsigned int event_frame_delay_value = GAME_FRAME_DELAY; - ClearField(); + ResetDelayCounter(&event_frame_delay); - for (y = 0; y < 3; y++) + if (!bitmaps_initialized) { - for (x = 0; x < 3; x++) - { - DrawFixedGraphic(xpos + x - 1, ypos + y - 1, IMG_MENU_CALIBRATE_BLUE, 0); - check[x][y] = FALSE; - } + controller = LoadCustomImage("joystick/controller.png"); + button = LoadCustomImage("joystick/button.png"); + axis_x = LoadCustomImage("joystick/axis_x.png"); + axis_y = LoadCustomImage("joystick/axis_y.png"); + + bitmaps_initialized = TRUE; } - DrawTextSCentered(mSY - SY + 6 * 32, FONT_TITLE_1, "Rotate joystick"); - DrawTextSCentered(mSY - SY + 7 * 32, FONT_TITLE_1, "in all directions"); - DrawTextSCentered(mSY - SY + 9 * 32, FONT_TITLE_1, "if all balls"); - DrawTextSCentered(mSY - SY + 10 * 32, FONT_TITLE_1, "are marked,"); - DrawTextSCentered(mSY - SY + 11 * 32, FONT_TITLE_1, "center joystick"); - DrawTextSCentered(mSY - SY + 12 * 32, FONT_TITLE_1, "and"); - DrawTextSCentered(mSY - SY + 13 * 32, FONT_TITLE_1, "press any button!"); + name = getFormattedJoystickName(SDL_JoystickName(joystick)); + +#if DEBUG_JOYSTICKS + /* print info about the joystick we are watching */ + Error(ERR_DEBUG, "watching joystick %d: (%s)\n", + SDL_JoystickInstanceID(joystick), name); + Error(ERR_DEBUG, "joystick has %d axes, %d hats, %d balls, and %d buttons\n", + SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick), + SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick)); +#endif - joy_value = Joystick(player_nr); - last_x = (joy_value & JOY_LEFT ? -1 : joy_value & JOY_RIGHT ? +1 : 0); - last_y = (joy_value & JOY_UP ? -1 : joy_value & JOY_DOWN ? +1 : 0); + /* initialize mapping with GUID and name */ + SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, sizeof(temp)); - /* eventually uncalibrated center position (joystick could be uncentered) */ - if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL)) - return FALSE; + snprintf(mapping, sizeof(mapping), "%s,%s,platform:%s,", + temp, name, SDL_GetPlatform()); - new_joystick_xmiddle = joy_x; - new_joystick_ymiddle = joy_y; + /* loop through all steps (buttons and axes), getting joystick events */ + for (i = 0; i < SDL_arraysize(steps) && !done;) + { + Bitmap *marker = button; /* initialize with reliable default value */ - DrawFixedGraphic(xpos + last_x, ypos + last_y, IMG_MENU_CALIBRATE_RED, 0); + step = &steps[i]; + strcpy(step->mapping, mapping); + step->axis = -1; + step->button = -1; + step->hat = -1; + step->hat_value = -1; - FadeIn(REDRAW_FIELD); + marker = (step->marker == MARKER_BUTTON ? button : + step->marker == MARKER_AXIS_X ? axis_x : + step->marker == MARKER_AXIS_Y ? axis_y : marker); - while (Joystick(player_nr) & JOY_BUTTON); /* wait for released button */ - InitAnimation(); + next = FALSE; - while (result < 0) - { - if (PendingEvent()) /* got event */ + while (!done && !next) { - Event event; + alpha += alpha_step * (int)(SDL_GetTicks() - alpha_ticks) / 5; + alpha_ticks = SDL_GetTicks(); - NextEvent(&event); + if (alpha >= 255) + { + alpha = 255; + alpha_step = -1; + } + else if (alpha < 128) + { + alpha = 127; + alpha_step = 1; + } - switch (event.type) + int controller_x = SX + (SXSIZE - controller->width) / 2; + int controller_y = SY + ystep_line; + + int marker_x = controller_x + step->x; + int marker_y = controller_y + step->y; + + int ystart1 = mSY - 2 * SY + controller_y + controller->height; + int ystart2 = ystart1 + ystep_name + ystep_line; + + ClearField(); + + DrawTextSCentered(ystart1, font_name, name); + + DrawTextSCentered(ystart2, font_info, + "Press buttons and move axes on"); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "your controller when indicated."); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "(Your controller may look different.)"); + ystart2 += ystep_para; + +#if defined(PLATFORM_ANDROID) + DrawTextSCentered(ystart2, font_info, + "To correct a mistake,"); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "press the 'back' button."); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "To skip a button or axis,"); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "press the 'menu' button."); +#else + DrawTextSCentered(ystart2, font_info, + "To correct a mistake,"); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "press the 'backspace' key."); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "To skip a button or axis,"); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "press the 'return' key."); + ystart2 += ystep_line; + DrawTextSCentered(ystart2, font_info, + "To exit, press the 'escape' key."); +#endif + + BlitBitmapMasked(controller, drawto, 0, 0, + controller->width, controller->height, + controller_x, controller_y); + + SDL_SetSurfaceAlphaMod(marker->surface_masked, alpha); + + BlitBitmapMasked(marker, drawto, 0, 0, + marker->width, marker->height, + marker_x, marker_y); + + if (!screen_initialized) + FadeIn(REDRAW_FIELD); + else + BackToFront(); + + screen_initialized = TRUE; + + while (NextValidEvent(&event)) { - case EVENT_KEYPRESS: - switch (GetEventKey((KeyEvent *)&event, TRUE)) - { - case KSYM_Return: - if (check_remaining == 0) - result = 1; + switch (event.type) + { + case SDL_JOYAXISMOTION: + if (event.jaxis.value > 20000 || + event.jaxis.value < -20000) + { + for (j = 0; j < i; j++) + if (steps[j].axis == event.jaxis.axis) + break; + + if (j == i) + { + if (step->marker != MARKER_AXIS_X && + step->marker != MARKER_AXIS_Y) + break; + + step->axis = event.jaxis.axis; + strcat(mapping, step->field); + snprintf(temp, sizeof(temp), ":a%u,", event.jaxis.axis); + strcat(mapping, temp); + i++; + next = TRUE; + } + } + + break; + + case SDL_JOYHATMOTION: + /* ignore centering; we're probably just coming back + to the center from the previous item we set */ + if (event.jhat.value == SDL_HAT_CENTERED) break; - case KSYM_Escape: - FadeSkipNextFadeIn(); - result = 0; + for (j = 0; j < i; j++) + if (steps[j].hat == event.jhat.hat && + steps[j].hat_value == event.jhat.value) + break; + + if (j == i) + { + step->hat = event.jhat.hat; + step->hat_value = event.jhat.value; + strcat(mapping, step->field); + snprintf(temp, sizeof(temp), ":h%u.%u,", + event.jhat.hat, event.jhat.value ); + strcat(mapping, temp); + i++; + next = TRUE; + } + + break; + + case SDL_JOYBALLMOTION: + break; + + case SDL_JOYBUTTONUP: + for (j = 0; j < i; j++) + if (steps[j].button == event.jbutton.button) + break; + + if (j == i) + { + step->button = event.jbutton.button; + strcat(mapping, step->field); + snprintf(temp, sizeof(temp), ":b%u,", event.jbutton.button); + strcat(mapping, temp); + i++; + next = TRUE; + } + + break; + + case SDL_FINGERDOWN: + case SDL_MOUSEBUTTONDOWN: + /* skip this step */ + i++; + next = TRUE; + + break; + + case SDL_KEYDOWN: + if (event.key.keysym.sym == KSYM_BackSpace || + event.key.keysym.sym == KSYM_Back) + { + if (i == 0) + { + /* leave screen */ + success = FALSE; + done = TRUE; + } + + /* undo this step */ + prev_step = &steps[i - 1]; + strcpy(mapping, prev_step->mapping); + i--; + next = TRUE; + break; + } + + if (event.key.keysym.sym == KSYM_space || + event.key.keysym.sym == KSYM_Return || + event.key.keysym.sym == KSYM_Menu) + { + /* skip this step */ + i++; + next = TRUE; - default: break; - } - break; + } - case EVENT_KEYRELEASE: - key_joystick_mapping = 0; - break; + if (event.key.keysym.sym == KSYM_Escape) + { + /* leave screen */ + success = FALSE; + done = TRUE; + } - default: - HandleOtherEvents(&event); + break; + + case SDL_QUIT: + program.exit_function(0); + break; + + default: + break; + } + + // do not handle events for longer than standard frame delay period + if (DelayReached(&event_frame_delay, event_frame_delay_value)) break; } } + } - if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL)) - return FALSE; - - new_joystick_xleft = MIN(new_joystick_xleft, joy_x); - new_joystick_xright = MAX(new_joystick_xright, joy_x); - new_joystick_yupper = MIN(new_joystick_yupper, joy_y); - new_joystick_ylower = MAX(new_joystick_ylower, joy_y); + if (success) + { +#if DEBUG_JOYSTICKS + Error(ERR_DEBUG, "New game controller mapping:\n\n%s\n\n", mapping); +#endif - setup.input[player_nr].joy.xleft = new_joystick_xleft; - setup.input[player_nr].joy.yupper = new_joystick_yupper; - setup.input[player_nr].joy.xright = new_joystick_xright; - setup.input[player_nr].joy.ylower = new_joystick_ylower; - setup.input[player_nr].joy.xmiddle = new_joystick_xmiddle; - setup.input[player_nr].joy.ymiddle = new_joystick_ymiddle; + // activate mapping for this game + SDL_GameControllerAddMapping(mapping); - CheckJoystickData(); + // save mapping to personal mappings + SaveSetup_AddGameControllerMapping(mapping); + } - joy_value = Joystick(player_nr); + /* wait until the last pending event was removed from event queue */ + while (NextValidEvent(&event)); - if (joy_value & JOY_BUTTON && check_remaining == 0) - result = 1; + return success; +#else + return TRUE; +#endif +} - x = (joy_value & JOY_LEFT ? -1 : joy_value & JOY_RIGHT ? +1 : 0); - y = (joy_value & JOY_UP ? -1 : joy_value & JOY_DOWN ? +1 : 0); +static int ConfigureJoystickMain(int player_nr) +{ + char *device_name = setup.input[player_nr].joy.device_name; + int joystick_nr = getJoystickNrFromDeviceName(device_name); + boolean joystick_active = CheckJoystickOpened(joystick_nr); + int success = FALSE; + int i; - if (x != last_x || y != last_y) - { - DrawFixedGraphic(xpos + last_x, ypos + last_y, - IMG_MENU_CALIBRATE_YELLOW, 0); - DrawFixedGraphic(xpos + x, ypos + y, - IMG_MENU_CALIBRATE_RED, 0); + if (joystick.status == JOYSTICK_NOT_AVAILABLE) + return JOYSTICK_NOT_AVAILABLE; - last_x = x; - last_y = y; + if (!joystick_active || !setup.input[player_nr].use_joystick) + return JOYSTICK_NOT_AVAILABLE; - if (check_remaining > 0 && !check[x+1][y+1]) - { - check[x+1][y+1] = TRUE; - check_remaining--; - } - } + FadeSetEnterMenu(); + FadeOut(REDRAW_FIELD); - DoAnimation(); - BackToFront(); + // close all joystick devices (potentially opened as game controllers) + for (i = 0; i < SDL_NumJoysticks(); i++) + SDLCloseJoystick(i); - /* don't eat all CPU time */ - Delay(10); - } + // open joystick device as plain joystick to configure as game controller + SDL_Joystick *joystick = SDL_JoystickOpen(joystick_nr); - /* calibrated center position (joystick should now be centered) */ - if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL)) + // as the joystick was successfully opened before, this should not happen + if (joystick == NULL) return FALSE; - new_joystick_xmiddle = joy_x; - new_joystick_ymiddle = joy_y; + // create new game controller mapping (buttons and axes) for joystick device + success = ConfigureJoystickMapButtonsAndAxes(joystick); - StopAnimation(); + // close joystick (and maybe re-open as configured game controller later) + SDL_JoystickClose(joystick); - /* wait until the last pressed button was released */ - while (Joystick(player_nr) & JOY_BUTTON) - { - if (PendingEvent()) /* got event */ - { - Event event; - - NextEvent(&event); - HandleOtherEvents(&event); + // re-open all joystick devices (potentially as game controllers) + for (i = 0; i < SDL_NumJoysticks(); i++) + SDLOpenJoystick(i); - Delay(10); - } - } + // clear all joystick input actions for all joystick devices + SDLClearJoystickState(); - return TRUE; + return (success ? JOYSTICK_CONFIGURED : JOYSTICK_NOT_CONFIGURED); } -void CalibrateJoystick(int player_nr) +void ConfigureJoystick(int player_nr) { - if (!CalibrateJoystickMain(player_nr)) + boolean state = ConfigureJoystickMain(player_nr); + + if (state != JOYSTICK_NOT_CONFIGURED) { + boolean success = (state == JOYSTICK_CONFIGURED); + char *message = (success ? " IS CONFIGURED! " : " NOT AVAILABLE! "); char *device_name = setup.input[player_nr].joy.device_name; int nr = getJoystickNrFromDeviceName(device_name) + 1; int xpos = mSX - SX; int ypos = mSY - SY; + unsigned int wait_frame_delay = 0; + unsigned int wait_frame_delay_value = 2000; + + ResetDelayCounter(&wait_frame_delay); ClearField(); DrawTextF(xpos + 16, ypos + 6 * 32, FONT_TITLE_1, " JOYSTICK %d ", nr); - DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, " NOT AVAILABLE! "); - BackToFront(); + DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, message); - Delay(2000); /* show error message for a short time */ + while (!DelayReached(&wait_frame_delay, wait_frame_delay_value)) + BackToFront(); ClearEventQueue(); } @@ -6507,10 +6968,6 @@ void CalibrateJoystick(int player_nr) void DrawSetupScreen() { - DeactivateJoystick(); - - SetMainBackgroundImage(IMG_BACKGROUND_SETUP); - if (setup_mode == SETUP_MODE_INPUT) DrawSetupScreen_Input(); else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED) @@ -6519,12 +6976,12 @@ void DrawSetupScreen() 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) DrawChooseTree(&window_size_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE) DrawChooseTree(&scaling_type_current); + else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING) + DrawChooseTree(&rendering_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS) DrawChooseTree(&artwork.gfx_current); else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS) @@ -6546,8 +7003,7 @@ void DrawSetupScreen() else DrawSetupScreen_Generic(); - PlayMenuSound(); - PlayMenuMusic(); + PlayMenuSoundsAndMusic(); } void RedrawSetupScreenAfterFullscreenToggle() @@ -6572,12 +7028,12 @@ void HandleSetupScreen(int mx, int my, int dx, int dy, int button) 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) HandleChooseTree(mx, my, dx, dy, button, &window_size_current); else if (setup_mode == SETUP_MODE_CHOOSE_SCALING_TYPE) HandleChooseTree(mx, my, dx, dy, button, &scaling_type_current); + else if (setup_mode == SETUP_MODE_CHOOSE_RENDERING) + HandleChooseTree(mx, my, dx, dy, button, &rendering_mode_current); else if (setup_mode == SETUP_MODE_CHOOSE_GRAPHICS) HandleChooseTree(mx, my, dx, dy, button, &artwork.gfx_current); else if (setup_mode == SETUP_MODE_CHOOSE_SOUNDS) @@ -6926,14 +7382,10 @@ static void CreateScreenScrollbars() void CreateScreenGadgets() { - int last_game_status = game_status; /* save current game status */ - CreateScreenMenubuttons(); CreateScreenScrollbuttons(); CreateScreenScrollbars(); - - game_status = last_game_status; /* restore current game status */ } void FreeScreenGadgets() @@ -7003,6 +7455,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: @@ -7012,6 +7466,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: @@ -7021,6 +7477,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: