mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-23 01:59:43 +01:00
Automatic menu buttons
This commit is contained in:
parent
018cbd98ed
commit
eea8741689
9 changed files with 214 additions and 28 deletions
|
@ -6602,41 +6602,62 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
}
|
||||
|
||||
currentmenuname = t;
|
||||
int buttonyoff = 0;
|
||||
bool buttonscentered = false;
|
||||
menuyoff = 0;
|
||||
int maxspacing = 30; // maximum value for menuspacing, can only become lower.
|
||||
bool auto_buttons = true;
|
||||
bool auto_center = true;
|
||||
menucountdown = 0;
|
||||
menuoptions.clear();
|
||||
touch::remove_dynamic_buttons();
|
||||
|
||||
switch (t)
|
||||
{
|
||||
case Menu::mainmenu:
|
||||
{
|
||||
if (ingame_titlemode)
|
||||
{
|
||||
/* We shouldn't be here! */
|
||||
SDL_assert(0 && "Entering main menu from in-game options!");
|
||||
break;
|
||||
}
|
||||
int offset = 0;
|
||||
#if !defined(MAKEANDPLAY)
|
||||
option(loc::gettext("play"));
|
||||
touch::create_menu_button(80, 96, 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++);
|
||||
if (loc::show_translator_menu)
|
||||
{
|
||||
option(loc::gettext("translator"));
|
||||
offset++;
|
||||
}
|
||||
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.
|
||||
|
||||
menuyoff = -10;
|
||||
maxspacing = 15;
|
||||
auto_buttons = false;
|
||||
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case Menu::playerworlds:
|
||||
buttonyoff = -16;
|
||||
option(loc::gettext("play a level"));
|
||||
option(loc::gettext("level editor"), !editor_disabled);
|
||||
if (!editor_disabled)
|
||||
{
|
||||
option(loc::gettext("open level folder"), FILESYSTEM_openDirectoryEnabled());
|
||||
option(loc::gettext("show level folder path"));
|
||||
option(loc::gettext("open level folder"), FILESYSTEM_openDirectoryEnabled(), PR_RTL_XFLIP, false);
|
||||
option(loc::gettext("show level folder path"), true, PR_RTL_XFLIP, false);
|
||||
}
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = -40;
|
||||
|
@ -6753,7 +6774,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
menuxoff = 20;
|
||||
menuyoff = 70-(menuoptions.size()*10);
|
||||
menuspacing = 5;
|
||||
return; // skip automatic centering, will turn out bad with levels list
|
||||
auto_center = false;
|
||||
}
|
||||
break;
|
||||
case Menu::quickloadlevel:
|
||||
|
@ -6792,6 +6813,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("return"));
|
||||
menuyoff = -10;
|
||||
maxspacing = 15;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::graphicoptions:
|
||||
if (!gameScreen.isForcedFullscreen())
|
||||
|
@ -6809,6 +6832,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("return"));
|
||||
menuyoff = -10;
|
||||
maxspacing = 15;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::ed_settings:
|
||||
option(loc::gettext("change description"));
|
||||
|
@ -6869,13 +6894,15 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("gameplay"));
|
||||
option(loc::gettext("graphics"));
|
||||
option(loc::gettext("audio"));
|
||||
option(loc::gettext("game pad"));
|
||||
option(loc::gettext("game pad"), true, PR_RTL_XFLIP, false);
|
||||
option(loc::gettext("touch input"));
|
||||
option(loc::gettext("accessibility"));
|
||||
option(loc::gettext("language"), !translator_cutscene_test);
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = 0;
|
||||
maxspacing = 15;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::speedrunneroptions:
|
||||
option(loc::gettext("glitchrunner mode"));
|
||||
|
@ -6887,6 +6914,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("return"));
|
||||
menuyoff = 0;
|
||||
maxspacing = 15;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::setglitchrunner:
|
||||
{
|
||||
|
@ -6932,6 +6961,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("return"));
|
||||
menuyoff = 0;
|
||||
maxspacing = 15;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::controller:
|
||||
option(loc::gettext("analog stick sensitivity"));
|
||||
|
@ -7048,7 +7079,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
menuxoff = 20;
|
||||
menuyoff = 55-(menuoptions.size()*10);
|
||||
menuspacing = 5;
|
||||
return; // skip automatic centering, will turn out bad with scripts list
|
||||
auto_center = false;
|
||||
break;
|
||||
case Menu::translator_maintenance:
|
||||
option(loc::gettext("sync language files"));
|
||||
option(loc::gettext("global statistics"), false);
|
||||
|
@ -7092,12 +7124,19 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("unlock secret lab"), !unlock[Unlock_SECRETLAB]);
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = -20;
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::credits:
|
||||
option(loc::gettext("next page"));
|
||||
option(loc::gettext("last page"));
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = 64;
|
||||
|
||||
touch::create_menu_button(46 - 16, 200, 76, 26, loc::gettext("last"), 1);
|
||||
touch::create_menu_button(122, 200, 76, 26, loc::gettext("return"), 2);
|
||||
touch::create_menu_button(198 + 16, 200, 76, 26, loc::gettext("next"), 0);
|
||||
auto_buttons = false;
|
||||
|
||||
break;
|
||||
case Menu::credits2:
|
||||
case Menu::credits25:
|
||||
|
@ -7110,12 +7149,22 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("previous page"));
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = 64;
|
||||
|
||||
touch::create_menu_button(46 - 16, 200, 76, 26, loc::gettext("previous"), 1);
|
||||
touch::create_menu_button(122, 200, 76, 26, loc::gettext("return"), 2);
|
||||
touch::create_menu_button(198 + 16, 200, 76, 26, loc::gettext("next"), 0);
|
||||
auto_buttons = false;
|
||||
break;
|
||||
case Menu::credits6:
|
||||
option(loc::gettext("first page"));
|
||||
option(loc::gettext("previous page"));
|
||||
option(loc::gettext("return"));
|
||||
menuyoff = 64;
|
||||
|
||||
touch::create_menu_button(46 - 16, 200, 76, 26, loc::gettext("previous"), 1);
|
||||
touch::create_menu_button(122, 200, 76, 26, loc::gettext("return"), 2);
|
||||
touch::create_menu_button(198 + 16, 200, 76, 26, loc::gettext("first"), 0);
|
||||
auto_buttons = false;
|
||||
break;
|
||||
case Menu::play:
|
||||
{
|
||||
|
@ -7230,6 +7279,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
}
|
||||
else
|
||||
{
|
||||
buttonscentered = true;
|
||||
if (save_exists())
|
||||
{
|
||||
option(loc::gettext("continue"));
|
||||
|
@ -7282,6 +7332,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
option(loc::gettext("return"));
|
||||
menuyoff = 8;
|
||||
maxspacing = 20;
|
||||
|
||||
buttonscentered = true;
|
||||
break;
|
||||
case Menu::intermissionmenu:
|
||||
option(loc::gettext("play intermission 1"));
|
||||
|
@ -7394,25 +7446,65 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
|
|||
break;
|
||||
}
|
||||
|
||||
// Automatically center the menu. We must check the width of the menu with the initial horizontal spacing.
|
||||
// If it's too wide, reduce the horizontal spacing by 5 and retry.
|
||||
// Try to limit the menu width to 272 pixels: 320 minus 16*2 for square brackets, minus 8*2 padding.
|
||||
// The square brackets fall outside the menu width (i.e. selected menu options are printed 16 pixels to the left)
|
||||
bool done_once = false;
|
||||
int menuwidth = 0;
|
||||
for (; !done_once || (menuwidth > 272 && menuspacing > 0); maxspacing -= 5)
|
||||
if (auto_center)
|
||||
{
|
||||
done_once = true;
|
||||
menuspacing = maxspacing;
|
||||
menuwidth = 0;
|
||||
for (size_t i = 0; i < menuoptions.size(); i++)
|
||||
// Automatically center the menu. We must check the width of the menu with the initial horizontal spacing.
|
||||
// If it's too wide, reduce the horizontal spacing by 5 and retry.
|
||||
// Try to limit the menu width to 272 pixels: 320 minus 16*2 for square brackets, minus 8*2 padding.
|
||||
// The square brackets fall outside the menu width (i.e. selected menu options are printed 16 pixels to the left)
|
||||
bool done_once = false;
|
||||
int menuwidth = 0;
|
||||
for (; !done_once || (menuwidth > 272 && menuspacing > 0); maxspacing -= 5)
|
||||
{
|
||||
int width = i*menuspacing + font::len(menuoptions[i].print_flags, menuoptions[i].text);
|
||||
if (width > menuwidth)
|
||||
menuwidth = width;
|
||||
done_once = true;
|
||||
menuspacing = maxspacing;
|
||||
menuwidth = 0;
|
||||
for (size_t i = 0; i < menuoptions.size(); i++)
|
||||
{
|
||||
int width = i * menuspacing + font::len(menuoptions[i].print_flags, menuoptions[i].text);
|
||||
if (width > menuwidth)
|
||||
menuwidth = width;
|
||||
}
|
||||
}
|
||||
menuxoff = (320 - menuwidth) / 2;
|
||||
}
|
||||
|
||||
if (auto_buttons)
|
||||
{
|
||||
int base_y = 128 + menuyoff + buttonyoff;
|
||||
|
||||
if (buttonscentered)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < menuoptions.size(); i++)
|
||||
{
|
||||
if (menuoptions[i].auto_button)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
base_y = (240 - count * 32) / 2;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < (int) menuoptions.size(); i++)
|
||||
{
|
||||
if (menuoptions[i].auto_button)
|
||||
{
|
||||
touch::create_menu_button(
|
||||
(320 - 160) / 2,
|
||||
base_y + offset * 32,
|
||||
160,
|
||||
26,
|
||||
menuoptions[i].text,
|
||||
i,
|
||||
menuoptions[i].active
|
||||
);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
menuxoff = (320-menuwidth)/2;
|
||||
}
|
||||
|
||||
bool Game::can_unlock_ndm(void)
|
||||
|
|
|
@ -31,6 +31,7 @@ struct MenuOption
|
|||
char text[MENU_TEXT_BYTES];
|
||||
bool active;
|
||||
uint32_t print_flags;
|
||||
bool auto_button;
|
||||
};
|
||||
|
||||
//Menu IDs
|
||||
|
@ -390,12 +391,13 @@ public:
|
|||
int menuspacing;
|
||||
std::vector<MenuStackFrame> menustack;
|
||||
|
||||
void inline option(const char* text, bool active = true, uint32_t print_flags = PR_RTL_XFLIP)
|
||||
void inline option(const char* text, bool active = true, uint32_t print_flags = PR_RTL_XFLIP, bool auto_button = true)
|
||||
{
|
||||
MenuOption menuoption;
|
||||
SDL_strlcpy(menuoption.text, text, sizeof(menuoption.text));
|
||||
menuoption.active = active;
|
||||
menuoption.print_flags = print_flags;
|
||||
menuoption.auto_button = auto_button;
|
||||
menuoptions.push_back(menuoption);
|
||||
}
|
||||
|
||||
|
|
|
@ -386,7 +386,7 @@ static void slidermodeinput(void)
|
|||
*user_changing_volume = SDL_clamp(*user_changing_volume, 0, USER_VOLUME_MAX);
|
||||
}
|
||||
|
||||
static void menuactionpress(void)
|
||||
void menuactionpress(void)
|
||||
{
|
||||
if (game.menutestmode)
|
||||
{
|
||||
|
@ -3172,6 +3172,7 @@ void mapinput(void)
|
|||
if (key.isDown(KEYBOARD_ENTER) || key.isDown(game.controllerButton_map)) game.press_map = true;
|
||||
if ((key.isDown(27) || touch::button_tapped(TOUCH_BUTTON_CANCEL)) && !game.mapheld)
|
||||
{
|
||||
touch::remove_dynamic_buttons();
|
||||
game.mapheld = true;
|
||||
if (game.menupage < 9
|
||||
|| (game.menupage >= 20 && game.menupage <= 21))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
void menuactionpress(void);
|
||||
|
||||
void titleinput(void);
|
||||
|
||||
void gameinput(void);
|
||||
|
|
|
@ -1948,7 +1948,15 @@ void titlerender(void)
|
|||
if(tg>255) tg=255;
|
||||
if (tb < 0) tb = 0;
|
||||
if(tb>255) tb=255;
|
||||
graphics.drawmenu(tr, tg, tb, game.currentmenuname);
|
||||
|
||||
if (key.using_touch)
|
||||
{
|
||||
touch::render_buttons(tr, tg, tb);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.drawmenu(tr, tg, tb, game.currentmenuname);
|
||||
}
|
||||
}
|
||||
|
||||
graphics.drawfade();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Enums.h"
|
||||
#include "Map.h"
|
||||
#include "Script.h"
|
||||
#include "Touch.h"
|
||||
#include "UtilityClass.h"
|
||||
|
||||
static inline void titleupdatetextcol(void)
|
||||
|
@ -227,6 +228,7 @@ void maprenderfixed(void)
|
|||
{
|
||||
graphics.menuoffset = threshold;
|
||||
//go back to gamemode!
|
||||
touch::remove_dynamic_buttons();
|
||||
game.mapheld = true;
|
||||
game.gamestate = GAMEMODE;
|
||||
graphics.resumegamemode = false;
|
||||
|
|
|
@ -2595,6 +2595,8 @@ void scriptclass::startgamemode(const enum StartMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
touch::remove_dynamic_buttons();
|
||||
|
||||
/* Containers which need to be reset before gameplay starts
|
||||
* ex. before custom levels get loaded */
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ namespace touch
|
|||
void init(void)
|
||||
{
|
||||
scale = 10;
|
||||
use_buttons = false;
|
||||
textbox_style = false;
|
||||
|
||||
for (int i = 0; i < NUM_TOUCH_BUTTONS; i++)
|
||||
{
|
||||
|
@ -92,12 +94,82 @@ namespace touch
|
|||
refresh_all_buttons();
|
||||
}
|
||||
|
||||
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;
|
||||
button.width = width;
|
||||
button.height = height;
|
||||
button.image = NULL;
|
||||
button.text = text;
|
||||
button.active = true;
|
||||
button.core = false;
|
||||
button.ui = false;
|
||||
button.down = false;
|
||||
button.pressed = false;
|
||||
button.fingerId = -1;
|
||||
button.type = TOUCH_BUTTON_TYPE_NONE;
|
||||
button.id = -1;
|
||||
button.disabled = false;
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
/* Helper function to create menu buttons (very common) in a single line */
|
||||
void create_menu_button(int x, int y, int width, int height, std::string text, int id)
|
||||
{
|
||||
TouchButton button = create_button(x, y, width, height, text);
|
||||
button.type = TOUCH_BUTTON_TYPE_MENU;
|
||||
button.id = id;
|
||||
|
||||
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);
|
||||
button.type = TOUCH_BUTTON_TYPE_MENU;
|
||||
button.id = id;
|
||||
button.disabled = !active;
|
||||
|
||||
register_button(button);
|
||||
}
|
||||
|
||||
void register_button(TouchButton button)
|
||||
{
|
||||
dynamic_buttons.push_back(button);
|
||||
|
||||
refresh_all_buttons();
|
||||
}
|
||||
|
||||
void remove_dynamic_buttons(void)
|
||||
{
|
||||
dynamic_buttons.clear();
|
||||
refresh_all_buttons();
|
||||
}
|
||||
|
||||
void on_button_up(TouchButton* button)
|
||||
{
|
||||
bool version2_2 = GlitchrunnerMode_less_than_or_equal(Glitchrunner2_2);
|
||||
switch (button->type)
|
||||
{
|
||||
case TOUCH_BUTTON_TYPE_MENU:
|
||||
game.currentmenuoption = button->id;
|
||||
menuactionpress();
|
||||
break;
|
||||
case TOUCH_BUTTON_TYPE_NONE:
|
||||
default:
|
||||
break;
|
||||
|
@ -165,12 +237,9 @@ namespace touch
|
|||
break;
|
||||
|
||||
case TITLEMODE:
|
||||
if (game.menustart)
|
||||
if (!game.menustart)
|
||||
{
|
||||
buttons[TOUCH_BUTTON_LEFT].active = true;
|
||||
buttons[TOUCH_BUTTON_RIGHT].active = true;
|
||||
buttons[TOUCH_BUTTON_CANCEL].active = true;
|
||||
buttons[TOUCH_BUTTON_CONFIRM].active = true;
|
||||
use_buttons = false;
|
||||
}
|
||||
break;
|
||||
case TELEPORTERMODE:
|
||||
|
|
|
@ -90,6 +90,14 @@ namespace touch
|
|||
void reset(void);
|
||||
void update_buttons(void);
|
||||
|
||||
TouchButton create_button(int x, int y, int width, int height, std::string text);
|
||||
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(int x, int y, int width, int height, std::string text, int id, bool disabled);
|
||||
|
||||
void remove_dynamic_buttons(void);
|
||||
|
||||
void on_button_up(TouchButton* button);
|
||||
|
||||
void init(void);
|
||||
|
|
Loading…
Reference in a new issue