1
0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-06-25 05:58:30 +02:00

Make menus automatically centered and narrowed

All menus had a hardcoded X position (offset to an arbitrary starting
point of 110) and a hardcoded horizontal spacing for the "staircasing"
(mostly 30 pixels, but for some specific menus hardcoded to 15, 20 or
something else). Not all menus were centered, and seem to have been
manually made narrower (with lower horizontal spacing) whenever text
ran offscreen during development.

This system may already be hard to work with in an English-only menu
system, since you may need to adjust horizontal spacing or positioning
when adding an option. The main reason I made this change is that it's
even less optimal when menu options have to be translated, since
maximum string lengths are hard to determine, and it's easy to have
menu options running offscreen, especially when not all menus are
checked for all languages and when options could be added in the middle
of a menu after translations of that menu are already checked.

Now, menus are automatically centered based on their options, and they
are automatically made narrower if they won't fit with the default
horizontal spacing of 30 pixels (with some padding). The game.menuxoff
variable for the menu X position is now also offset to 0 instead of 110

The _default_ horizontal spacing can be changed on a per-menu basis,
and most menus (not all) which already had a narrower spacing set,
retain that as a maximum spacing, simply because they looked odd with
30 pixels of spacing (especially the main menu). They will be made even
narrower automatically if needed. In the most extreme case, the spacing
can go down to 0 and options will be displayed right below each other.
This isn't in the usual style of the game, but at least we did the best
we could to prevent options running offscreen.

The only exception to automatic menu centering and narrowing is the
list of player levels, because it's a special case and existing
behavior would be better than automatic centering there.
This commit is contained in:
Dav999-v 2020-06-29 02:09:52 +02:00
parent 22738cdb97
commit 0023c821db
6 changed files with 50 additions and 82 deletions

View File

@ -6958,8 +6958,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
currentmenuoption = 0;
currentmenuname = t;
menuxoff = 0;
menuyoff = 0;
int maxspacing = 30; // maximum value for menuspacing, can only become lower.
menucountdown = 0;
menuoptions.clear();
@ -6978,8 +6978,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("view credits");
#endif
option("quit game");
menuxoff = -16;
menuyoff = -10;
maxspacing = 15;
break;
#if !defined(NO_CUSTOM_LEVELS)
case Menu::playerworlds:
@ -6989,14 +6989,13 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
#endif
option("open level folder", FILESYSTEM_openDirectoryEnabled());
option("back to menu");
menuxoff = -30;
menuyoff = -40;
maxspacing = 15;
break;
case Menu::levellist:
if(ed.ListOfMetaData.size()==0)
{
option("ok");
menuxoff = 0;
menuyoff = -20;
}
else
@ -7057,8 +7056,10 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
}
option("return to menu");
menuxoff = -90;
menuxoff = 20;
menuyoff = 70-(menuoptions.size()*10);
menuspacing = 5;
return; // skip automatic centering, will turn out bad with levels list
}
break;
#endif
@ -7066,18 +7067,15 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("continue from save");
option("start from beginning");
option("back to levels");
menuxoff = -40;
menuyoff = -30;
break;
case Menu::youwannaquit:
option("yes, quit");
option("no, return");
menuxoff = 0;
menuyoff = -20;
break;
case Menu::errornostart:
option("ok");
menuxoff = 0;
menuyoff = -20;
break;
case Menu::graphicoptions:
@ -7089,7 +7087,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("toggle fps");
option("toggle vsync");
option("return");
menuxoff = -85;
menuyoff = 0;
break;
case Menu::ed_settings:
@ -7101,8 +7098,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("save level");
option("quit to main menu");
menuxoff = -46;
menuyoff = -20;
maxspacing = 15;
break;
case Menu::ed_desc:
option("change name");
@ -7111,21 +7108,21 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("change website");
option("back to settings");
menuxoff = -40;
menuyoff = 6;
maxspacing = 15;
break;
case Menu::ed_music:
option("next song");
option("back");
menuxoff = -10;
menuyoff = 16;
maxspacing = 15;
break;
case Menu::ed_quit:
option("yes, save and quit");
option("no, quit without saving");
option("return to editor");
menuxoff = -50;
menuyoff = 8;
maxspacing = 15;
break;
case Menu::options:
option("accessibility options");
@ -7140,7 +7137,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
}
option("return");
menuxoff = -40;
menuyoff = 0;
break;
case Menu::accessibility:
@ -7152,7 +7148,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("load screen");
option("room name bg");
option("return");
menuxoff = -85;
menuyoff = -10;
break;
case Menu::controller:
@ -7161,19 +7156,16 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("bind enter");
option("bind menu");
option("return");
menuxoff = -40;
menuyoff = 10;
break;
case Menu::cleardatamenu:
option("no! don't delete");
option("yes, delete everything");
menuxoff = -30;
menuyoff = 64;
break;
case Menu::setinvincibility:
option("no, return to options");
option("yes, enable");
menuxoff = -30;
menuyoff = 64;
break;
case Menu::setslowdown:
@ -7181,7 +7173,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("80% speed");
option("60% speed");
option("40% speed");
menuxoff = -40;
menuyoff = 16;
break;
case Menu::unlockmenu:
@ -7192,56 +7183,48 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("unlock ship jukebox", (stat_trinkets<20));
option("unlock secret lab", !unlock[8]);
option("return");
menuxoff = -70;
menuyoff = -20;
break;
case Menu::credits:
option("next page");
option("last page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits2:
option("next page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits25:
option("next page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits3:
option("next page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits4:
option("next page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits5:
option("next page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::credits6:
option("first page");
option("previous page");
option("return");
menuxoff = 20;
menuyoff = 64;
break;
case Menu::play:
@ -7357,12 +7340,10 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("return");
if (unlock[8])
{
menuxoff = -40;
menuyoff = -30;
}
else
{
menuxoff = -20;
menuyoff = -40;
}
}
@ -7375,13 +7356,11 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
case Menu::unlockintermission:
case Menu::unlockflipmode:
option("continue");
menuxoff = 20;
menuyoff = 70;
break;
case Menu::newgamewarning:
option("start new game");
option("return to menu");
menuxoff = -30;
menuyoff = 64;
break;
case Menu::playmodes:
@ -7390,14 +7369,13 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("no death mode", unlock[17] && !map.invincibility && slowdown == 30);
option("flip mode", unlock[18]);
option("return to play menu");
menuxoff = -70;
menuyoff = 8;
maxspacing = 20;
break;
case Menu::intermissionmenu:
option("play intermission 1");
option("play intermission 2");
option("return to play menu");
menuxoff = -50;
menuyoff = -35;
break;
case Menu::playint1:
@ -7406,7 +7384,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("Verdigris");
option("Victoria");
option("return");
menuxoff = -60;
menuyoff = 10;
break;
case Menu::playint2:
@ -7415,7 +7392,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("Verdigris");
option("Victoria");
option("return");
menuxoff = -60;
menuyoff = 10;
break;
case Menu::continuemenu:
@ -7423,14 +7399,12 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("continue from teleporter");
option("continue from quicksave");
option("return to play menu");
menuxoff = -60;
menuyoff = 20;
break;
case Menu::startnodeathmode:
option("disable cutscenes");
option("enable cutscenes");
option("return to play menu");
menuxoff = -60;
menuyoff = 40;
break;
case Menu::gameover:
@ -7439,7 +7413,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
break;
case Menu::gameover2:
option("return to play menu");
menuxoff = -25;
menuyoff = 80;
break;
case Menu::unlockmenutrials:
@ -7451,7 +7424,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option("the final level", !unlock[14]);
option("return to unlock menu");
menuxoff = -80;
menuyoff = 0;
break;
case Menu::timetrials:
@ -7463,8 +7435,8 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option(unlock[14] ? "the final level" : "???", unlock[14]);
option("return to play menu");
menuxoff = -80;
menuyoff = 0;
maxspacing = 15;
break;
case Menu::nodeathmodecomplete:
menucountdown = 90;
@ -7472,7 +7444,6 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
break;
case Menu::nodeathmodecomplete2:
option("return to play menu");
menuxoff = -25;
menuyoff = 70;
break;
case Menu::timetrialcomplete:
@ -7486,15 +7457,31 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
case Menu::timetrialcomplete3:
option("return to play menu");
option("try again");
menuxoff = -25;
menuyoff = 70;
break;
case Menu::gamecompletecontinue:
option("return to play menu");
menuxoff = -25;
menuyoff = 70;
break;
}
// Automatically center the menu. We must check the width of the menu with the initial horizontal spacing.
// If it doesn't fit onscreen (including square brackets), reduce the horizontal spacing by 5 and retry.
bool done_once = false;
int menuwidth = 0;
for (; !done_once || (menuwidth > 272 && maxspacing > 0); maxspacing -= 5)
{
done_once = true;
menuspacing = maxspacing;
menuwidth = 0;
for (size_t i = 0; i < menuoptions.size(); i++)
{
int width = i*menuspacing + graphics.len(menuoptions[i].text);
if (width > menuwidth)
menuwidth = width;
}
}
menuxoff = (320-menuwidth)/2;
}
void Game::deletequick()

View File

@ -218,6 +218,7 @@ public:
enum Menu::MenuName kludge_ingametemp;
int current_credits_list_index;
int menuxoff, menuyoff;
int menuspacing;
std::vector<MenuStackFrame> menustack;
void inline option(std::string text, bool active = true)

View File

@ -1242,7 +1242,7 @@ void Graphics::processfade()
}
}
void Graphics::drawmenu( int cr, int cg, int cb, int division /*= 30*/ )
void Graphics::drawmenu( int cr, int cg, int cb )
{
for (size_t i = 0; i < game.menuoptions.size(); i++)
{
@ -1254,14 +1254,14 @@ void Graphics::drawmenu( int cr, int cg, int cb, int division /*= 30*/ )
std::string tempstring = game.menuoptions[i].text;
std::transform(tempstring.begin(), tempstring.end(),tempstring.begin(), ::toupper);
tempstring = std::string("[ ") + tempstring + std::string(" ]");
Print(110 + (i * division) - 16 +game.menuxoff, 140 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
Print((i * game.menuspacing) - 16 +game.menuxoff, 140 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
}
else
{
std::string tempstring = game.menuoptions[i].text;
tempstring = "[ " + tempstring + " ]";
//Draw it in gray
Print(110 + (i * division) - 16 +game.menuxoff, 140 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
Print((i * game.menuspacing) - 16 +game.menuxoff, 140 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
}
}
else
@ -1269,18 +1269,18 @@ void Graphics::drawmenu( int cr, int cg, int cb, int division /*= 30*/ )
//Draw it normally
if (game.menuoptions[i].active)
{
Print(110 + (i * division) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
Print((i * game.menuspacing) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
}
else
{
//Draw it in gray
Print(110 + (i * division) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
Print((i * game.menuspacing) +game.menuxoff, 140 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
}
}
}
}
void Graphics::drawlevelmenu( int cr, int cg, int cb, int division /*= 30*/ )
void Graphics::drawlevelmenu( int cr, int cg, int cb )
{
for (size_t i = 0; i < game.menuoptions.size(); i++)
{
@ -1293,14 +1293,14 @@ void Graphics::drawlevelmenu( int cr, int cg, int cb, int division /*= 30*/ )
std::string tempstring = game.menuoptions[i].text;
std::transform(tempstring.begin(), tempstring.end(),tempstring.begin(), ::toupper);
tempstring = std::string("[ ") + tempstring + std::string(" ]");
Print(110 + (i * division) - 16 +game.menuxoff, 140+8 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
Print((i * game.menuspacing) - 16 +game.menuxoff, 140+8 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
}
else
{
std::string tempstring = game.menuoptions[i].text;
tempstring = "[ " + tempstring + " ]";
//Draw it in gray
Print(110 + (i * division) - 16 +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
Print((i * game.menuspacing) - 16 +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
}
}else{
//Draw it highlighted
@ -1309,14 +1309,14 @@ void Graphics::drawlevelmenu( int cr, int cg, int cb, int division /*= 30*/ )
std::string tempstring = game.menuoptions[i].text;
std::transform(tempstring.begin(), tempstring.end(),tempstring.begin(), ::toupper);
tempstring = std::string("[ ") + tempstring + std::string(" ]");
Print(110 + (i * division) - 16 +game.menuxoff, 144 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
Print((i * game.menuspacing) - 16 +game.menuxoff, 144 + (i * 12) +game.menuyoff, tempstring, cr, cg, cb);
}
else
{
std::string tempstring = game.menuoptions[i].text;
tempstring = "[ " + tempstring + " ]";
//Draw it in gray
Print(110 + (i * division) - 16 +game.menuxoff, 144 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
Print((i * game.menuspacing) - 16 +game.menuxoff, 144 + (i * 12)+game.menuyoff, tempstring, 128, 128, 128);
}
}
}
@ -1326,23 +1326,23 @@ void Graphics::drawlevelmenu( int cr, int cg, int cb, int division /*= 30*/ )
//Draw it normally
if (game.menuoptions[i].active)
{
Print(110 + (i * division) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
Print((i * game.menuspacing) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
}
else
{
//Draw it in gray
Print(110 + (i * division) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
Print((i * game.menuspacing) +game.menuxoff, 140+8 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
}
}else{
//Draw it normally
if (game.menuoptions[i].active)
{
Print(110 + (i * division) +game.menuxoff, 144 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
Print((i * game.menuspacing) +game.menuxoff, 144 + (i * 12)+game.menuyoff, game.menuoptions[i].text, cr, cg, cb);
}
else
{
//Draw it in gray
Print(110 + (i * division) +game.menuxoff, 144 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
Print((i * game.menuspacing) +game.menuxoff, 144 + (i * 12)+game.menuyoff, game.menuoptions[i].text, 128, 128, 128);
}
}
}

View File

@ -46,8 +46,8 @@ public:
void drawcoloredtile(int x, int y, int t, int r, int g, int b);
void drawmenu(int cr, int cg, int cb, int division = 30);
void drawlevelmenu(int cr, int cg, int cb, int division = 30);
void drawmenu(int cr, int cg, int cb);
void drawlevelmenu(int cr, int cg, int cb);
void processfade();

View File

@ -1103,29 +1103,9 @@ void titlerender()
if(tg>255) tg=255;
if (tb < 0) tb = 0;
if(tb>255) tb=255;
if (game.currentmenuname == Menu::timetrials || game.currentmenuname == Menu::unlockmenutrials)
if (game.currentmenuname == Menu::levellist)
{
graphics.drawmenu(tr, tg, tb, 15);
}
else if (game.currentmenuname == Menu::unlockmenu)
{
graphics.drawmenu(tr, tg, tb, 15);
}
else if (game.currentmenuname == Menu::playmodes)
{
graphics.drawmenu(tr, tg, tb, 20);
}
else if (game.currentmenuname == Menu::mainmenu)
{
graphics.drawmenu(tr, tg, tb, 15);
}
else if (game.currentmenuname == Menu::playerworlds)
{
graphics.drawmenu(tr, tg, tb, 15);
}
else if (game.currentmenuname == Menu::levellist)
{
graphics.drawlevelmenu(tr, tg, tb, 5);
graphics.drawlevelmenu(tr, tg, tb);
}
else
{

View File

@ -3143,7 +3143,7 @@ void editorrender()
if(tb>255) tb=255;
editormenurender(tr, tg, tb);
graphics.drawmenu(tr, tg, tb, 15);
graphics.drawmenu(tr, tg, tb);
}
else if(ed.scripttextmod)
{