diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index b96a4018..b43a0f2e 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -377,6 +377,8 @@ void Game::init(void) screenshot_border_timer = 0; screenshot_saved_success = false; + languagepage = 0; + setdefaultcontrollerbuttons(); } @@ -6566,7 +6568,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) bool auto_buttons = true; bool auto_center = true; int button_height = 26; - int button_spacing = 6; + int button_spacing = 8; menucountdown = 0; menuoptions.clear(); touch::remove_dynamic_buttons(); @@ -6584,12 +6586,12 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) int offset = 0; #if !defined(MAKEANDPLAY) option(loc::gettext("play")); - touch::create_menu_button(80, 96, 160, 26, loc::gettext("play"), offset++); + touch::create_menu_button(80, 96 - 8, 160, 26, loc::gettext("play"), offset++); #endif option(loc::gettext("levels")); option(loc::gettext("options")); - touch::create_menu_button(80, 128, 160, 26, loc::gettext("levels"), offset++); - touch::create_menu_button(164, 160, 76, 26, loc::gettext("options"), offset++); + touch::create_menu_button(80, 130 - 8, 160, 26, loc::gettext("levels"), offset++); + touch::create_menu_button(80, 164 - 8, 128, 26, loc::gettext("options"), offset++); if (loc::show_translator_menu) { option(loc::gettext("translator")); @@ -6598,15 +6600,19 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) option(loc::gettext("credits")); option(loc::gettext("quit")); - touch::create_menu_button(80, 160, 76, 26, loc::gettext("credits"), offset++); - touch::create_menu_button(80, 192, 160, 26, loc::gettext("quit"), offset++); // TODO: Don't show this on phones! Fine for now, but we have to do it before submitting to app stores. + // Create the language button + TouchButton button = touch::create_button(214, 164 - 8, 26, 26, ""); + button.type = TOUCH_BUTTON_TYPE_MENU_LANGUAGE; + button.id = -1; + + touch::register_button(button); + + touch::create_menu_button(80, 198 - 8, 160, 26, loc::gettext("credits"), offset++); menuyoff = -10; maxspacing = 15; auto_buttons = false; - - break; } case Menu::playerworlds: @@ -7017,19 +7023,45 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) } else { + int button_x = 80; + int button_y = 32; + bool spawn_more_buttons = true; for (size_t i = 0; i < loc::languagelist.size(); i++) { if (loc::languagelist[i].nativename.empty()) { option(loc::languagelist[i].code.c_str()); + + if (spawn_more_buttons) + { + int button_width = SDL_max(120, font::len(PR_1X, loc::languagelist[i].code.c_str()) + 16); + touch::create_menu_button(button_x - button_width / 2, button_y, button_width, 16, loc::languagelist[i].code.c_str(), i); + } } else { + Uint8 flags = PR_FONT_IDX(loc::languagelist[i].font_idx, loc::languagelist[i].rtl); option( loc::languagelist[i].nativename.c_str(), true, - PR_FONT_IDX(loc::languagelist[i].font_idx, loc::languagelist[i].rtl) + flags ); + + if (spawn_more_buttons) + { + int button_width = SDL_max(120, font::len(flags, loc::languagelist[i].nativename.c_str()) + 16); + touch::create_menu_button_flags(button_x - button_width / 2, button_y, button_width, 16, loc::languagelist[i].nativename.c_str(), i, flags); + } + } + button_y += 20; + if (button_y > 200 - 16) + { + button_y = 32; + button_x += 160; + if (button_x > 320 - 80) + { + spawn_more_buttons = false; + } } } @@ -7356,7 +7388,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ ) option(loc::gettext("start new game")); option(loc::gettext("return")); menuyoff = 64; - buttonyoff = -16; + buttonyoff = -32; break; case Menu::playmodes: option(loc::gettext("time trials"), !nocompetitive_unless_translator()); diff --git a/desktop_version/src/Game.h b/desktop_version/src/Game.h index 5afe1a3a..3eebc25c 100644 --- a/desktop_version/src/Game.h +++ b/desktop_version/src/Game.h @@ -605,6 +605,8 @@ public: int old_screenshot_border_timer; int screenshot_border_timer; bool screenshot_saved_success; + + int languagepage; }; #ifndef GAME_DEFINITION diff --git a/desktop_version/src/GraphicsResources.cpp b/desktop_version/src/GraphicsResources.cpp index 49364cdc..1a364f0b 100644 --- a/desktop_version/src/GraphicsResources.cpp +++ b/desktop_version/src/GraphicsResources.cpp @@ -432,6 +432,7 @@ void GraphicsResources::init(void) im_button_left = LoadImage("graphics/buttons/button_left.png"); im_button_right = LoadImage("graphics/buttons/button_right.png"); im_button_map = LoadImage("graphics/buttons/button_map.png"); + im_button_globe = LoadImage("graphics/buttons/button_globe.png"); im_sprites_translated = NULL; im_flipsprites_translated = NULL; @@ -484,6 +485,7 @@ void GraphicsResources::destroy(void) CLEAR(im_button_left); CLEAR(im_button_right); CLEAR(im_button_map); + CLEAR(im_button_globe); #undef CLEAR VVV_freefunc(SDL_FreeSurface, im_sprites_surf); diff --git a/desktop_version/src/GraphicsResources.h b/desktop_version/src/GraphicsResources.h index a2ed89ab..5938cc46 100644 --- a/desktop_version/src/GraphicsResources.h +++ b/desktop_version/src/GraphicsResources.h @@ -53,6 +53,7 @@ public: SDL_Texture* im_button_left; SDL_Texture* im_button_right; SDL_Texture* im_button_map; + SDL_Texture* im_button_globe; }; SDL_Surface* LoadImageSurface(const char* filename); diff --git a/desktop_version/src/Input.cpp b/desktop_version/src/Input.cpp index e9f85d98..9ba2a850 100644 --- a/desktop_version/src/Input.cpp +++ b/desktop_version/src/Input.cpp @@ -423,6 +423,17 @@ void menuactionpress(void) #undef OPTION_ID + // Special case for touch input: language button! + if (option_id == -1) + { + music.playef(Sound_VIRIDIAN); + loc::loadlanguagelist(); + loc::pre_title_lang_menu = false; + game.createmenu(Menu::language); + game.currentmenuoption = loc::languagelist_curlang; + map.nexttowercolour(); + break; + } switch (option_id) { @@ -905,10 +916,11 @@ void menuactionpress(void) } if (game.currentmenuoption == -1) { - // language menu + // gameplay menu music.playef(Sound_VIRIDIAN); - game.createmenu(Menu::language, true); + game.createmenu(Menu::gameplayoptions, true); map.nexttowercolour(); + break; } int accessibilityoffset = 0; @@ -1066,10 +1078,11 @@ void menuactionpress(void) if (game.currentmenuoption == -2) { - // language menu + // accessibility menu music.playef(Sound_VIRIDIAN); - game.createmenu(Menu::language, true); + game.createmenu(Menu::accessibility, true); map.nexttowercolour(); + break; } if (game.currentmenuoption == -1) { @@ -1212,32 +1225,57 @@ void menuactionpress(void) music.playef(Sound_VIRIDIAN); - if (loc::languagelist.size() != 0 && (unsigned)game.currentmenuoption < loc::languagelist.size()) + if (game.currentmenuoption == -3) { - /* Update code also used in KeyPoll.cpp. */ - loc::languagelist_curlang = game.currentmenuoption; - loc::lang = loc::languagelist[game.currentmenuoption].code; - loc::loadtext(false); - loc::lang_set = loc::lang_set_current; - graphics.grphx.init_translations(); + // return + game.returnmenu(); + map.nexttowercolour(); + } + else if (game.currentmenuoption == -2) + { + // go left a page (or wrap to end) + game.languagepage--; + map.nexttowercolour(); + } + else if (game.currentmenuoption == -1) + { + // go right a page (or wrap to start) + game.languagepage++; + map.nexttowercolour(); + } + else + { + if (loc::languagelist.size() != 0 && (unsigned)game.currentmenuoption < loc::languagelist.size()) + { + /* Update code also used in KeyPoll.cpp. */ + loc::languagelist_curlang = game.currentmenuoption; + loc::lang = loc::languagelist[game.currentmenuoption].code; + loc::loadtext(false); + loc::lang_set = loc::lang_set_current; + graphics.grphx.init_translations(); + } + + if (loc::pre_title_lang_menu) + { + /* Make the title screen appear, we haven't seen it yet. + * game.returnmenu() works because Menu::mainmenu + * is created before the language menu. */ + game.menustart = false; + loc::pre_title_lang_menu = false; + } + + if (prev_lang != loc::lang) + { + recomputetextboxes(); + } + + if (!key.using_touch) + { + game.returnmenu(); + map.nexttowercolour(); + } } - if (loc::pre_title_lang_menu) - { - /* Make the title screen appear, we haven't seen it yet. - * game.returnmenu() works because Menu::mainmenu - * is created before the language menu. */ - game.menustart = false; - loc::pre_title_lang_menu = false; - } - - if (prev_lang != loc::lang) - { - recomputetextboxes(); - } - - game.returnmenu(); - map.nexttowercolour(); game.savestatsandsettings_menu(); break; diff --git a/desktop_version/src/Render.cpp b/desktop_version/src/Render.cpp index 4a9a8f0a..f8e6e72f 100644 --- a/desktop_version/src/Render.cpp +++ b/desktop_version/src/Render.cpp @@ -205,7 +205,13 @@ static void menurender(void) { case Menu::mainmenu: { - const int temp = 50; + int temp = 50; + + if (key.using_touch) + { + temp = 38; + } + graphics.draw_sprite((160 - 96) + 0 * 32, temp, 23, tr, tg, tb); graphics.draw_sprite((160 - 96) + 1 * 32, temp, 23, tr, tg, tb); graphics.draw_sprite((160 - 96) + 2 * 32, temp, 23, tr, tg, tb); @@ -841,22 +847,25 @@ static void menurender(void) else if ((unsigned)game.currentmenuoption < loc::languagelist.size()) { font::print_wrap(PR_CEN, -1, 8, loc::languagelist[game.currentmenuoption].credit.c_str(), tr/2, tg/2, tb/2); - const char* select_hint; - char buffer[SCREEN_WIDTH_CHARS + 1]; - if (BUTTONGLYPHS_keyboard_is_active()) + if (!key.using_touch) { - select_hint = loc::languagelist[game.currentmenuoption].action_hint.c_str(); + const char* select_hint; + char buffer[SCREEN_WIDTH_CHARS + 1]; + if (BUTTONGLYPHS_keyboard_is_active()) + { + select_hint = loc::languagelist[game.currentmenuoption].action_hint.c_str(); + } + else + { + vformat_buf(buffer, sizeof(buffer), + loc::languagelist[game.currentmenuoption].gamepad_hint.c_str(), + "button:but", + vformat_button(ActionSet_Menu, Action_Menu_Accept) + ); + select_hint = buffer; + } + font::print(PR_CEN, -1, 230, select_hint, tr / 2, tg / 2, tb / 2); } - else - { - vformat_buf(buffer, sizeof(buffer), - loc::languagelist[game.currentmenuoption].gamepad_hint.c_str(), - "button:but", - vformat_button(ActionSet_Menu, Action_Menu_Accept) - ); - select_hint = buffer; - } - font::print(PR_CEN, -1, 230, select_hint, tr/2, tg/2, tb/2); } break; case Menu::translator_main: diff --git a/desktop_version/src/Touch.cpp b/desktop_version/src/Touch.cpp index 386d4faf..bff0cc88 100644 --- a/desktop_version/src/Touch.cpp +++ b/desktop_version/src/Touch.cpp @@ -97,18 +97,6 @@ namespace touch TouchButton create_button(int x, int y, int width, int height, std::string text) { - int scale = get_scale(); - - if (width == -1) - { - width = font::len(PR_CEN | (SDL_min((scale - 1), 7) << 0), text.c_str()) + 24 * scale; - } - - if (height == -1) - { - height = font::height(PR_CEN | (SDL_min((scale - 1), 7) << 0)) + 18 * scale; - } - TouchButton button; button.x = x; button.y = y; @@ -126,6 +114,7 @@ namespace touch button.id = -1; button.disabled = false; button.checked = false; + button.flags = 0; return button; } @@ -140,6 +129,16 @@ namespace touch register_button(button); } + void create_menu_button_flags(int x, int y, int width, int height, std::string text, int id, Uint8 flags) + { + TouchButton button = create_button(x, y, width, height, text); + button.type = TOUCH_BUTTON_TYPE_MENU; + button.id = id; + button.flags = flags; + + register_button(button); + } + void create_menu_button(int x, int y, int width, int height, std::string text, int id, bool active) { TouchButton button = create_button(x, y, width, height, text); @@ -195,6 +194,7 @@ namespace touch button->checked = !button->checked; SDL_FALLTHROUGH; case TOUCH_BUTTON_TYPE_MENU: + case TOUCH_BUTTON_TYPE_MENU_LANGUAGE: game.currentmenuoption = button->id; menuactionpress(); break; @@ -367,7 +367,7 @@ namespace touch int offset = (button->down) ? 1 : 0; int font_scale = (SDL_min((scale - 1), 7) << 0); - int height = font::height(PR_CJK_LOW | font_scale); + int height = font::height(PR_CJK_LOW | font_scale | button->flags); switch (button->type) { @@ -389,7 +389,7 @@ namespace touch graphics.fill_rect((button->x + sliderpos + 1) * scale, (button->y + (button->height / 2) - 4) * scale, 8, 8, use_r / inner_div, use_g / inner_div, use_b / inner_div); - font::print(PR_CEN | PR_CJK_LOW | font_scale, button->x + (button->width / 2) * scale, button->y * scale, button->text, use_r, use_g, use_b); + font::print(PR_CEN | PR_CJK_LOW | font_scale | button->flags, button->x + (button->width / 2) * scale, button->y * scale, button->text, use_r, use_g, use_b); break; } case TOUCH_BUTTON_TYPE_MENU_TOGGLE: @@ -399,14 +399,23 @@ namespace touch graphics.fill_rect(button->x + 2 * scale + offset * scale, button->y + 2 * scale + offset * scale, 6, 6, use_r, use_g, use_b); } - font::print(PR_CJK_LOW | font_scale, button->x + 16 + offset * scale, button->y + ((button->height - height) / 2 + offset) * scale, button->text, use_r, use_g, use_b); + font::print(PR_CJK_LOW | font_scale | button->flags, button->x + 16 + offset * scale, button->y + ((button->height - height) / 2 + offset) * scale, button->text, use_r, use_g, use_b); break; default: graphics.fill_rect(button->x + 4 * scale, button->y + 4 * scale, button->width, button->height, r / shadow_div, g / shadow_div, b / shadow_div); graphics.fill_rect(button->x + offset * scale, button->y + offset * scale, button->width, button->height, use_r, use_g, use_b); graphics.fill_rect(button->x + (offset + 2) * scale, button->y + (2 + offset) * scale, button->width - 4 * scale, button->height - 4 * scale, use_r / inner_div, use_g / inner_div, use_b / inner_div); - font::print(PR_CEN | PR_CJK_LOW | font_scale, button->x + (button->width / 2) + offset * scale, button->y + ((button->height - height) / 2 + offset) * scale, button->text, 196, 196, 255 - help.glow); + if (button->type == TOUCH_BUTTON_TYPE_MENU_LANGUAGE) + { + graphics.set_texture_color_mod(graphics.grphx.im_button_globe, 196, 196, 255 - help.glow); + graphics.draw_texture(graphics.grphx.im_button_globe, (button->x + 4 + offset) * scale, (button->y + 4 + offset) * scale, scale, scale); + graphics.set_texture_color_mod(graphics.grphx.im_button_globe, 255, 255, 255); + } + else + { + font::print(PR_CEN | PR_CJK_LOW | font_scale | button->flags, button->x + (button->width / 2) + offset * scale, button->y + ((button->height - height) / 2 + offset) * scale, button->text, 196, 196, 255 - help.glow); + } break; } } diff --git a/desktop_version/src/Touch.h b/desktop_version/src/Touch.h index 29ab5ed9..887b25d5 100644 --- a/desktop_version/src/Touch.h +++ b/desktop_version/src/Touch.h @@ -56,6 +56,7 @@ enum TouchButtonType { TOUCH_BUTTON_TYPE_NONE, TOUCH_BUTTON_TYPE_MENU, + TOUCH_BUTTON_TYPE_MENU_LANGUAGE, TOUCH_BUTTON_TYPE_MENU_TOGGLE, TOUCH_BUTTON_TYPE_MENU_SLIDER, TOUCH_BUTTON_TYPE_MAP @@ -79,6 +80,7 @@ struct TouchButton int max; // If this is a slider, this is the maximum value int* var; // If this is a slider, this is the variable to modify std::string text; // The text for the button, if it doesn't have an image + Uint8 flags; // Print flags SDL_Texture* image; // The image that gets displayed on the button, can be NULL SDL_FingerID fingerId; TouchButtonType type; @@ -103,6 +105,7 @@ namespace touch void register_button(TouchButton button); void create_menu_button(int x, int y, int width, int height, std::string text, int id); + void create_menu_button_flags(int x, int y, int width, int height, std::string text, int id, Uint8 flags); void create_menu_button(int x, int y, int width, int height, std::string text, int id, bool disabled); void create_slider_button(int x, int y, int width, int height, std::string text, int* var, int minvalue, int maxvalue); void create_toggle_button(int x, int y, int width, int height, std::string text, int id, bool checked); diff --git a/desktop_version/touch/buttons/button_globe.png b/desktop_version/touch/buttons/button_globe.png new file mode 100644 index 00000000..6d4143dd Binary files /dev/null and b/desktop_version/touch/buttons/button_globe.png differ diff --git a/desktop_version/touch/buttons/button_quit.png b/desktop_version/touch/buttons/button_quit.png new file mode 100644 index 00000000..cf944ed2 Binary files /dev/null and b/desktop_version/touch/buttons/button_quit.png differ