1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-22 17:49:43 +01:00

Add menu for selecting the level font

By default, when you open the level editor to start a new level, the
level font will now match your VVVVVV language; so if you're, say,
Japanese, then you can make Japanese levels from the get-go. If you
want to make levels for a different target audience, you can change the
font via a new menu (map settings > change description > change font).
The game will remember this choice and it will become the new initial
level font.
This commit is contained in:
Dav999-v 2023-01-21 19:06:30 +01:00 committed by Misa Elizabeth Kai
parent b030ce568f
commit 9747843c18
14 changed files with 220 additions and 3 deletions

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<font_metadata>
<display_name>english/…</display_name>
<width>8</width>
<height>8</height>
<white_teeth>1</white_teeth>

View file

@ -513,6 +513,10 @@
<string english="change author" translation="canvia lautor" explanation="level editor menu option"/>
<string english="change description" translation="canvia la descripció" explanation="level editor menu option"/>
<string english="change website" translation="canvia el lloc web" explanation="level editor menu option"/>
<string english="change font" translation="" explanation="level editor menu option"/>
<string english="Level Font" translation="" explanation="title, editor, font that a custom level will show up in. You can select a language name here (like Chinese or Japanese which have different fonts, or `other`)" max="20"/>
<string english="Select the language in which the text in this level is written." translation="" explanation="" max="38*3"/>
<string english="Font: " translation="" explanation="level options, followed by name of font (mind the space)" max="14"/>
<string english="Map Music" translation="Música del mapa" explanation="title, editor, music that starts playing when a level is started. Can be changed with scripting later, so this is really just initial music" max="20"/>
<string english="Current map music:" translation="Música del mapa actual:" explanation="editor, followed by the number and name of a song, or `No background music`. Can be changed with scripting later, so this is really just initial music" max="38*2"/>
<string english="No background music" translation="No hi ha música de fons" explanation="editor, level starts with no song playing" max="38*2"/>

View file

@ -513,6 +513,10 @@
<string english="change author" translation="" explanation="level editor menu option"/>
<string english="change description" translation="" explanation="level editor menu option"/>
<string english="change website" translation="" explanation="level editor menu option"/>
<string english="change font" translation="" explanation="level editor menu option"/>
<string english="Level Font" translation="" explanation="title, editor, font that a custom level will show up in. You can select a language name here (like Chinese or Japanese which have different fonts, or `other`)" max="20"/>
<string english="Select the language in which the text in this level is written." translation="" explanation="" max="38*3"/>
<string english="Font: " translation="" explanation="level options, followed by name of font (mind the space)" max="14"/>
<string english="Map Music" translation="" explanation="title, editor, music that starts playing when a level is started. Can be changed with scripting later, so this is really just initial music" max="20"/>
<string english="Current map music:" translation="" explanation="editor, followed by the number and name of a song, or `No background music`. Can be changed with scripting later, so this is really just initial music" max="38*2"/>
<string english="No background music" translation="" explanation="editor, level starts with no song playing" max="38*2"/>

View file

@ -513,6 +513,10 @@
<string english="change author" translation="ŝanĝi aŭtoron" explanation="level editor menu option"/>
<string english="change description" translation="ŝanĝi priskribon" explanation="level editor menu option"/>
<string english="change website" translation="ŝanĝi retejon" explanation="level editor menu option"/>
<string english="change font" translation="ŝanĝi tiparon" explanation="level editor menu option"/>
<string english="Level Font" translation="Nivela tiparo" explanation="title, editor, font that a custom level will show up in. You can select a language name here (like Chinese or Japanese which have different fonts, or `other`)" max="20"/>
<string english="Select the language in which the text in this level is written." translation="Elektu la lingvon, en kiu la teksto en ĉi tiu nivelo estas skribita." explanation="" max="38*3"/>
<string english="Font: " translation="" explanation="level options, followed by name of font (mind the space)" max="14"/>
<string english="Map Music" translation="Fonmuziko" explanation="title, editor, music that starts playing when a level is started. Can be changed with scripting later, so this is really just initial music" max="20"/>
<string english="Current map music:" translation="Nuna fonmuziko:" explanation="editor, followed by the number and name of a song, or `No background music`. Can be changed with scripting later, so this is really just initial music" max="38*2"/>
<string english="No background music" translation="Neniu" explanation="editor, level starts with no song playing" max="38*2"/>

View file

@ -513,6 +513,10 @@
<string english="change author" translation="cambiar autor" explanation="level editor menu option"/>
<string english="change description" translation="cambiar descripcion" explanation="level editor menu option"/>
<string english="change website" translation="cambiar sitio web" explanation="level editor menu option"/>
<string english="change font" translation="" explanation="level editor menu option"/>
<string english="Level Font" translation="" explanation="title, editor, font that a custom level will show up in. You can select a language name here (like Chinese or Japanese which have different fonts, or `other`)" max="20"/>
<string english="Select the language in which the text in this level is written." translation="" explanation="" max="38*3"/>
<string english="Font: " translation="" explanation="level options, followed by name of font (mind the space)" max="14"/>
<string english="Map Music" translation="" explanation="title, editor, music that starts playing when a level is started. Can be changed with scripting later, so this is really just initial music" max="20"/>
<string english="Current map music:" translation="" explanation="editor, followed by the number and name of a song, or `No background music`. Can be changed with scripting later, so this is really just initial music" max="38*2"/>
<string english="No background music" translation="" explanation="editor, level starts with no song playing" max="38*2"/>

View file

@ -513,6 +513,10 @@
<string english="change author" translation="auteur wijzigen" explanation="level editor menu option"/>
<string english="change description" translation="beschrijving wijzigen" explanation="level editor menu option"/>
<string english="change website" translation="website wijzigen" explanation="level editor menu option"/>
<string english="change font" translation="lettertype wijzigen" explanation="level editor menu option"/>
<string english="Level Font" translation="Levellettertype" explanation="title, editor, font that a custom level will show up in. You can select a language name here (like Chinese or Japanese which have different fonts, or `other`)" max="20"/>
<string english="Select the language in which the text in this level is written." translation="Kies de taal waarin de tekst in dit level is geschreven." explanation="" max="38*3"/>
<string english="Font: " translation="Lettertype: " explanation="level options, followed by name of font (mind the space)" max="14"/>
<string english="Map Music" translation="Levelmuziek" explanation="title, editor, music that starts playing when a level is started. Can be changed with scripting later, so this is really just initial music" max="20"/>
<string english="Current map music:" translation="Huidige levelmuziek:" explanation="editor, followed by the number and name of a song, or `No background music`. Can be changed with scripting later, so this is really just initial music" max="38*2"/>
<string english="No background music" translation="Geen achtergrondmuziek" explanation="editor, level starts with no song playing" max="38*2"/>

View file

@ -430,6 +430,14 @@ static void editormenurender(int tr, int tg, int tb)
{
font::print(PR_CEN | PR_FONT_LEVEL, -1, 60+sp*5, cl.Desc3, tr, tg, tb);
}
const char* label = loc::gettext("Font: ");
int len_label = font::len(0, label);
const char* name = font::get_level_font_display_name();
font::print(0, 2, 230, label, tr/2, tg/2, tb/2);
font::print(PR_FONT_LEVEL, 2+len_label, 230, name, tr/2, tg/2, tb/2);
break;
}
case Menu::ed_music:
@ -498,6 +506,19 @@ static void editormenurender(int tr, int tg, int tb)
case Menu::ed_quit:
font::print_wrap(PR_CEN, -1, 90, loc::gettext("Save before quitting?"), tr, tg, tb);
break;
case Menu::ed_font:
{
font::print(PR_2X | PR_CEN, -1, 30, loc::gettext("Level Font"), tr, tg, tb);
font::print_wrap(PR_CEN, -1, 65, loc::gettext("Select the language in which the text in this level is written."), tr, tg, tb);
const char* label = loc::gettext("Font: ");
int len_label = font::len(0, label);
const char* name = font::get_level_font_display_name();
font::print(0, 2, 230, label, tr/2, tg/2, tb/2);
font::print(PR_FONT_LEVEL, 2+len_label, 230, name, tr/2, tg/2, tb/2);
break;
}
default:
break;
}
@ -1864,6 +1885,10 @@ static void editormenuactionpress(void)
key.keybuffer=cl.website;
break;
case 4:
game.createmenu(Menu::ed_font);
map.nexttowercolour();
break;
case 5:
game.returnmenu();
map.nexttowercolour();
break;
@ -2003,6 +2028,25 @@ static void editormenuactionpress(void)
break;
}
break;
case Menu::ed_font:
{
uint8_t idx_selected = font::font_idx_options[game.currentmenuoption];
cl.level_font_name = font::get_main_font_name(idx_selected);
if (idx_selected == loc::get_langmeta()->font_idx)
{
loc::new_level_font = "";
}
else
{
loc::new_level_font = cl.level_font_name;
}
font::set_level_font(cl.level_font_name.c_str());
music.playef(11);
game.returnmenu();
map.nexttowercolour();
game.savestatsandsettings_menu();
break;
}
default:
break;
}
@ -2099,7 +2143,7 @@ void editorinput(void)
}
else
{
bool esc_from_font = false;
music.playef(11);
if (ed.settingsmod)
{
@ -2113,6 +2157,13 @@ void editorinput(void)
{
ed.settingsmod = false;
}
else if (game.currentmenuname == Menu::ed_font)
{
// Prevent double return
esc_from_font = true;
game.returnmenu();
map.nexttowercolour();
}
else
{
game.returnmenu();
@ -2125,7 +2176,7 @@ void editorinput(void)
ed.settingsmod = true;
}
if (ed.settingsmod)
if (ed.settingsmod && !esc_from_font)
{
bool edsettings_in_stack = game.currentmenuname == Menu::ed_settings;
if (!edsettings_in_stack)

View file

@ -5,6 +5,7 @@
#include "Alloc.h"
#include "Constants.h"
#include "CustomLevels.h"
#include "FileSystemUtils.h"
#include "Graphics.h"
#include "GraphicsUtil.h"
@ -37,6 +38,7 @@ struct GlyphInfo
struct Font
{
char name[64];
char display_name[SCREEN_WIDTH_CHARS + 1];
uint8_t glyph_w;
uint8_t glyph_h;
@ -70,6 +72,9 @@ static FontContainer fonts_custom = {};
static uint8_t font_idx_8x8 = 0;
uint8_t font_idx_options_n = 0;
uint8_t font_idx_options[20];
static bool font_level_is_interface = false;
static bool font_idx_level_is_custom = false;
static uint8_t font_idx_level = 0;
@ -218,6 +223,7 @@ static uint8_t load_font(FontContainer* container, const char* name)
SDL_snprintf(name_txt, sizeof(name_txt), "graphics/%s.txt", name);
SDL_snprintf(name_xml, sizeof(name_xml), "graphics/%s.fontmeta", name);
SDL_strlcpy(f->name, name, sizeof(f->name));
SDL_strlcpy(f->display_name, name, sizeof(f->display_name));
f->glyph_w = 8;
f->glyph_h = 8;
@ -236,6 +242,10 @@ static uint8_t load_font(FontContainer* container, const char* name)
xml_loaded = true;
hDoc = hDoc.FirstChildElement("font_metadata");
if ((pElem = hDoc.FirstChildElement("display_name").ToElement()) != NULL)
{
SDL_strlcpy(f->display_name, pElem->GetText(), sizeof(f->display_name));
}
if ((pElem = hDoc.FirstChildElement("width").ToElement()) != NULL)
{
f->glyph_w = help.Int(pElem->GetText());
@ -405,6 +415,11 @@ uint8_t get_font_idx_8x8(void)
return font_idx_8x8;
}
bool level_font_is_main_idx(const uint8_t idx)
{
return !font_idx_level_is_custom && font_idx_level == idx;
}
void set_level_font(const char* name)
{
/* Apply the choice for a certain level-specific font.
@ -439,6 +454,33 @@ void set_level_font_interface(void)
font_level_is_interface = true;
}
void set_level_font_new(void)
{
/* Set the level font to the default font for new levels.
* This function is for starting the editor. */
font_level_is_interface = false;
font_idx_level_is_custom = false;
if (loc::new_level_font == "")
{
/* Just take the language's font
* (Japanese VVVVVV can make Japanese levels by default, etc) */
font_idx_level = loc::get_langmeta()->font_idx;
}
else
{
/* If the user has changed the font (wants to make levels
* for a different userbase) then remember that choice. */
if (!find_main_font_by_name(loc::new_level_font.c_str(), &font_idx_level))
{
font_idx_level = font_idx_8x8;
}
}
#ifndef NO_CUSTOM_LEVELS
cl.level_font_name = get_main_font_name(font_idx_level);
#endif
}
static void load_font_filename(bool is_custom, const char* filename)
{
// Load font.png, and everything that matches *.fontmeta (but not font.fontmeta)
@ -478,6 +520,23 @@ void load_main(void)
}
FILESYSTEM_freeEnumerate(&handle);
font_idx_level = font_idx_8x8;
// Initialize the font menu options, 8x8 font first
font_idx_options[0] = font_idx_8x8;
font_idx_options_n = 1;
for (uint8_t i = 0; i < fonts_main.count; i++)
{
if (i == font_idx_8x8)
{
continue;
}
font_idx_options[font_idx_options_n++] = i;
if (font_idx_options_n >= sizeof(font_idx_options))
{
break;
}
}
}
void load_custom(const char* name)
@ -884,6 +943,55 @@ const char* get_main_font_name(uint8_t idx)
return f->name;
}
const char* get_main_font_display_name(uint8_t idx)
{
Font* f = container_get(&fonts_main, idx);
if (f == NULL)
{
return "";
}
if (idx == font_idx_8x8)
{
// Deciding the name for the 8x8 font was harder than I'd like to admit.
if (loc::lang == "en" || loc::get_langmeta()->font_idx != font_idx_8x8)
{
// If you use English, or a CJK language: "english/..."
SDL_strlcpy(
f->display_name,
"english/…",
sizeof(f->display_name)
);
}
else
{
// If you use another, e.g. German: "english/deutsch/..."
SDL_snprintf(
f->display_name, sizeof(f->display_name),
"english/%s/…",
loc::get_langmeta()->nativename.c_str()
);
}
}
return f->display_name;
}
const char* get_level_font_display_name(void)
{
if (font_idx_level_is_custom)
{
Font* f = container_get(&fonts_custom, font_idx_level);
if (f == NULL)
{
return "";
}
return f->display_name;
}
return get_main_font_display_name(font_idx_level);
}
bool glyph_dimensions(uint32_t flags, uint8_t* glyph_w, uint8_t* glyph_h)
{
/* Gets the dimensions (glyph_w and glyph_h) of a certain font.

View file

@ -59,13 +59,20 @@
namespace font
{
// Options in font selection menu
extern uint8_t font_idx_options_n;
extern uint8_t font_idx_options[20];
bool find_main_font_by_name(const char* name, uint8_t* idx);
const char* get_main_font_name(uint8_t idx);
const char* get_main_font_display_name(uint8_t idx);
const char* get_level_font_display_name(void);
uint8_t get_font_idx_8x8(void);
bool level_font_is_main_idx(uint8_t idx);
void set_level_font(const char* name);
void set_level_font_interface(void);
void set_level_font_new(void);
void load_main(void);
void load_custom(const char* name);
void unload_custom(void);

View file

@ -4560,6 +4560,11 @@ void Game::deserializesettings(tinyxml2::XMLElement* dataNode, struct ScreenSett
loc::lang_set = help.Int(pText);
}
if (SDL_strcmp(pKey, "new_level_font") == 0)
{
loc::new_level_font = std::string(pText);
}
if (SDL_strcmp(pKey, "roomname_translator") == 0 && loc::show_translator_menu)
{
roomname_translator::set_enabled(help.Int(pText));
@ -4837,6 +4842,7 @@ void Game::serializesettings(tinyxml2::XMLElement* dataNode, const struct Screen
xml::update_tag(dataNode, "lang", loc::lang.c_str());
xml::update_tag(dataNode, "lang_set", (int) loc::lang_set);
xml::update_tag(dataNode, "new_level_font", loc::new_level_font.c_str());
xml::update_tag(dataNode, "roomname_translator", (int) roomname_translator::enabled);
}
@ -6375,6 +6381,7 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
option(loc::gettext("change author"));
option(loc::gettext("change description"));
option(loc::gettext("change website"));
option(loc::gettext("change font"));
option(loc::gettext("return"));
menuyoff = 6;
@ -6394,6 +6401,23 @@ void Game::createmenu( enum Menu::MenuName t, bool samemenu/*= false*/ )
menuyoff = 8;
maxspacing = 15;
break;
case Menu::ed_font:
{
int option_match = -1;
for (uint8_t i = 0; i < font::font_idx_options_n; i++)
{
uint8_t idx = font::font_idx_options[i];
option(font::get_main_font_display_name(idx), true, PR_FONT_IDX(idx));
if (font::level_font_is_main_idx(idx))
{
option_match = i;
}
}
currentmenuoption = option_match != -1 ? option_match : 0;
maxspacing = 15;
break;
}
case Menu::options:
option(loc::gettext("gameplay"));
option(loc::gettext("graphics"));

View file

@ -53,6 +53,7 @@ namespace Menu
ed_desc,
ed_music,
ed_quit,
ed_font,
options,
gameplayoptions,
speedrunneroptions,

View file

@ -15,6 +15,7 @@ namespace loc
bool lang_set = false;
std::string lang = "en";
std::string lang_custom = "";
std::string new_level_font = "";
LangMeta langmeta;
// language screen list

View file

@ -46,6 +46,7 @@ struct TextboxFormat
extern bool lang_set;
extern std::string lang;
extern std::string lang_custom;
extern std::string new_level_font;
extern LangMeta langmeta;
extern std::vector<LangMeta> languagelist;
extern int languagelist_curlang;

View file

@ -2592,13 +2592,16 @@ void scriptclass::startgamemode(const enum StartMode mode)
game.gamestate = GAMEMODE;
}
// Font handling
switch (mode)
{
case Start_EDITOR:
case Start_EDITORPLAYTESTING:
case Start_CUSTOM:
case Start_CUSTOM_QUICKSAVE:
break;
case Start_EDITOR:
font::set_level_font_new();
break;
default:
font::set_level_font_interface();
}