mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2024-12-22 17:49:43 +01:00
Add font containers for global and custom fonts
All global fonts and all custom fonts in a level are now loaded, and added to their respective "vectors". The selected font is still always as the global font.png, and the custom level font also isn't selected yet, but it's now easier to implement that. Also, I added FILESYSTEM_enumerateAssets, which #902 already has but I needed it now. I also rewrote it to not use std::vector<std::string>. That was my idea, it's also how FILESYSTEM_getLanguageCodes worked, so for symmetry, that function is getting changed as well.
This commit is contained in:
parent
22dcc29d45
commit
83d645c8e3
5 changed files with 179 additions and 31 deletions
|
@ -1,3 +1,5 @@
|
|||
#include "FileSystemUtils.h"
|
||||
|
||||
#include <physfs.h>
|
||||
#include <SDL.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -521,8 +523,6 @@ void FILESYSTEM_loadZip(const char* filename)
|
|||
}
|
||||
}
|
||||
|
||||
void FILESYSTEM_unmountAssets(void);
|
||||
|
||||
bool FILESYSTEM_mountAssets(const char* path)
|
||||
{
|
||||
const char* real_dir = PHYSFS_getRealDir(path);
|
||||
|
@ -1042,26 +1042,96 @@ void FILESYSTEM_enumerateLevelDirFileNames(
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> FILESYSTEM_getLanguageCodes(void)
|
||||
const char* FILESYSTEM_enumerate(const char* folder, EnumHandle* handle)
|
||||
{
|
||||
std::vector<std::string> list;
|
||||
char** fileList = PHYSFS_enumerateFiles("lang");
|
||||
char** item;
|
||||
/* List all files in a folder with PHYSFS_enumerateFiles.
|
||||
*
|
||||
* Doing it this way means we can decide and filter
|
||||
* what's in the lists (in wrapper functions).
|
||||
*
|
||||
* Called like this:
|
||||
*
|
||||
* EnumHandle handle = {};
|
||||
* const char* item;
|
||||
* while ((item = FILESYSTEM_enumerate("graphics", &handle)) != NULL)
|
||||
* {
|
||||
* puts(item);
|
||||
* }
|
||||
* FILESYSTEM_freeEnumerate(&handle);
|
||||
*/
|
||||
|
||||
for (item = fileList; *item != NULL; item++)
|
||||
if (handle->physfs_list == NULL)
|
||||
{
|
||||
char fullName[128];
|
||||
SDL_snprintf(fullName, sizeof(fullName), "lang/%s", *item);
|
||||
// First iteration, set things up
|
||||
handle->physfs_list = PHYSFS_enumerateFiles(folder);
|
||||
handle->_item = handle->physfs_list;
|
||||
}
|
||||
|
||||
if (FILESYSTEM_isDirectory(fullName) && *item[0] != '.')
|
||||
/* Return the next item, and increment the pointer.
|
||||
* (once we return NULL, handle->_item points to 1 past end of array) */
|
||||
return *(handle->_item++);
|
||||
}
|
||||
|
||||
const char* FILESYSTEM_enumerateAssets(const char* folder, EnumHandle* handle)
|
||||
{
|
||||
/* This function enumerates ONLY level-specific assets.
|
||||
* If there are only global assets and no level-specific ones,
|
||||
* we want an empty list.
|
||||
*
|
||||
* This function is called the same way as FILESYSTEM_enumerate, see above. */
|
||||
|
||||
if (!FILESYSTEM_isAssetMounted(folder))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char mounted_path[MAX_PATH];
|
||||
getMountedPath(mounted_path, sizeof(mounted_path), folder);
|
||||
|
||||
const char* item;
|
||||
while ((item = FILESYSTEM_enumerate(mounted_path, handle)) != NULL)
|
||||
{
|
||||
char full_name[128];
|
||||
SDL_snprintf(full_name, sizeof(full_name), "%s/%s", mounted_path, item);
|
||||
if (FILESYSTEM_isFile(full_name) && item[0] != '.')
|
||||
{
|
||||
list.push_back(*item);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
PHYSFS_freeList(fileList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return list;
|
||||
const char* FILESYSTEM_enumerateLanguageCodes(EnumHandle* handle)
|
||||
{
|
||||
/* This function enumerates all the language codes.
|
||||
*
|
||||
* This function is called the same way as FILESYSTEM_enumerate, see above. */
|
||||
|
||||
const char* item;
|
||||
while ((item = FILESYSTEM_enumerate("lang", handle)) != NULL)
|
||||
{
|
||||
char full_name[128];
|
||||
SDL_snprintf(full_name, sizeof(full_name), "lang/%s", item);
|
||||
|
||||
if (FILESYSTEM_isDirectory(full_name) && item[0] != '.')
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FILESYSTEM_freeEnumerate(EnumHandle* handle)
|
||||
{
|
||||
/* Call this function after enumerating with FILESYSTEM_enumerate or friends. */
|
||||
if (handle == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PHYSFS_freeList(handle->physfs_list);
|
||||
}
|
||||
|
||||
static int PLATFORM_getOSDirectory(char* output, const size_t output_size)
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
class binaryBlob;
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Forward declaration, including the entirety of tinyxml2.h across all files this file is included in is unnecessary
|
||||
namespace tinyxml2 { class XMLDocument; }
|
||||
|
@ -49,7 +47,16 @@ bool FILESYSTEM_loadAssetTiXml2Document(const char *name, tinyxml2::XMLDocument&
|
|||
|
||||
void FILESYSTEM_enumerateLevelDirFileNames(void (*callback)(const char* filename));
|
||||
|
||||
std::vector<std::string> FILESYSTEM_getLanguageCodes(void);
|
||||
struct EnumHandle
|
||||
{
|
||||
char** physfs_list;
|
||||
char** _item;
|
||||
};
|
||||
|
||||
const char* FILESYSTEM_enumerate(const char* folder, EnumHandle* handle);
|
||||
const char* FILESYSTEM_enumerateAssets(const char* folder, EnumHandle* handle);
|
||||
const char* FILESYSTEM_enumerateLanguageCodes(EnumHandle* handle);
|
||||
void FILESYSTEM_freeEnumerate(EnumHandle* handle);
|
||||
|
||||
bool FILESYSTEM_levelDirHasError(void);
|
||||
void FILESYSTEM_clearLevelDirError(void);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Graphics.h"
|
||||
#include "Localization.h"
|
||||
#include "UtilityClass.h"
|
||||
#include "Vlogging.h"
|
||||
#include "XMLUtils.h"
|
||||
|
||||
// Sigh... This is the second forward-declaration, we need to put this in a header file
|
||||
|
@ -17,7 +18,14 @@ SDL_Texture* LoadImage(const char *filename, const TextureLoadType loadtype);
|
|||
namespace font
|
||||
{
|
||||
|
||||
Font temp_bfont; // replace with like, a vector of all loaded fonts
|
||||
static FontContainer fonts_main = {};
|
||||
static FontContainer fonts_custom = {};
|
||||
|
||||
static size_t font_idx_interface = 0;
|
||||
static size_t font_idx_8x8 = 0;
|
||||
|
||||
static bool font_idx_custom_is_custom = false;
|
||||
static size_t font_idx_custom = 0;
|
||||
|
||||
static void codepoint_split(
|
||||
const uint32_t codepoint,
|
||||
|
@ -134,8 +142,19 @@ static bool decode_xml_range(tinyxml2::XMLElement* elem, unsigned* start, unsign
|
|||
return true;
|
||||
}
|
||||
|
||||
static void load_font(Font* f, const char* name)
|
||||
static size_t load_font(FontContainer* container, const char* name)
|
||||
{
|
||||
Font* new_fonts = (Font*) SDL_realloc(container->fonts, sizeof(Font)*(container->count+1));
|
||||
if (new_fonts == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
container->fonts = new_fonts;
|
||||
size_t f_idx = container->count++;
|
||||
Font* f = &container->fonts[f_idx];
|
||||
|
||||
vlog_info("Loading font \"%s\"...", name);
|
||||
|
||||
char name_png[256];
|
||||
char name_txt[256];
|
||||
char name_xml[256];
|
||||
|
@ -180,7 +199,7 @@ static void load_font(Font* f, const char* name)
|
|||
|
||||
if (f->image == NULL)
|
||||
{
|
||||
return;
|
||||
return f_idx;
|
||||
}
|
||||
|
||||
/* We may have a 2.3-style font.txt with all the characters.
|
||||
|
@ -300,17 +319,63 @@ static void load_font(Font* f, const char* name)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return f_idx;
|
||||
}
|
||||
|
||||
static void load_font_filename(bool is_custom, const char* filename)
|
||||
{
|
||||
// Load font.png, and everything that matches *.fontmeta (but not font.fontmeta)
|
||||
size_t expected_ext_start;
|
||||
bool is_fontpng = SDL_strcmp(filename, "font.png") == 0;
|
||||
if (is_fontpng)
|
||||
{
|
||||
expected_ext_start = SDL_strlen(filename)-4;
|
||||
}
|
||||
else
|
||||
{
|
||||
expected_ext_start = SDL_strlen(filename)-9;
|
||||
}
|
||||
if (is_fontpng || (endsWith(filename, ".fontmeta") && SDL_strcmp(filename, "font.fontmeta") != 0))
|
||||
{
|
||||
char font_name[128];
|
||||
SDL_strlcpy(font_name, filename, sizeof(font_name));
|
||||
font_name[SDL_min(127, expected_ext_start)] = '\0';
|
||||
|
||||
size_t f_idx = load_font(is_custom ? &fonts_custom : &fonts_main, font_name);
|
||||
|
||||
if (is_fontpng && !is_custom)
|
||||
{
|
||||
font_idx_8x8 = f_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load_main(void)
|
||||
{
|
||||
// TODO PHYSFS_enumerateFiles, load everything that matches *.fontmeta or font.png (but not font.fontmeta)
|
||||
load_font(&temp_bfont, "font");
|
||||
// Load all global fonts
|
||||
EnumHandle handle = {};
|
||||
const char* item;
|
||||
while ((item = FILESYSTEM_enumerate("graphics", &handle)) != NULL)
|
||||
{
|
||||
load_font_filename(false, item);
|
||||
}
|
||||
FILESYSTEM_freeEnumerate(&handle);
|
||||
}
|
||||
|
||||
void load_custom(void)
|
||||
{
|
||||
// Custom (level-specific assets) fonts NYI
|
||||
// Load all custom (level-specific assets) fonts
|
||||
unload_custom();
|
||||
EnumHandle handle = {};
|
||||
const char* item;
|
||||
while ((item = FILESYSTEM_enumerateAssets("graphics", &handle)) != NULL)
|
||||
{
|
||||
load_font_filename(true, item);
|
||||
}
|
||||
FILESYSTEM_freeEnumerate(&handle);
|
||||
|
||||
// TODO: decide font_idx_custom
|
||||
}
|
||||
|
||||
void unload_custom(void)
|
||||
|
@ -322,7 +387,7 @@ void unload_custom(void)
|
|||
void destroy(void)
|
||||
{
|
||||
/* Unload all fonts (main and custom) for exiting */
|
||||
Font* f = &temp_bfont;
|
||||
Font* f = &fonts_main.fonts[font_idx_8x8]; // TODO!
|
||||
VVV_freefunc(SDL_DestroyTexture, f->image);
|
||||
|
||||
for (int i = 0; i < FONT_N_PAGES; i++)
|
||||
|
@ -358,7 +423,7 @@ static bool next_wrap(
|
|||
goto next;
|
||||
}
|
||||
|
||||
linewidth += get_advance(&font::temp_bfont, str[idx]);
|
||||
linewidth += get_advance(&fonts_main.fonts[font_idx_8x8], str[idx]); // TODO get font via argument!
|
||||
|
||||
switch (str[idx])
|
||||
{
|
||||
|
@ -581,7 +646,7 @@ static Font* fontsel_to_font(int sel)
|
|||
{
|
||||
/* Take font selection integer (0-31) and turn it into the correct Font */
|
||||
// TODO handle all these cases here like 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 etc
|
||||
return &font::temp_bfont;
|
||||
return &fonts_main.fonts[font_idx_8x8];
|
||||
}
|
||||
|
||||
#define FLAG_PART(start, count) ((flags >> start) % (1 << count))
|
||||
|
|
|
@ -60,6 +60,12 @@ struct Font
|
|||
GlyphInfo* glyph_page[FONT_N_PAGES];
|
||||
};
|
||||
|
||||
struct FontContainer
|
||||
{
|
||||
size_t count;
|
||||
Font* fonts;
|
||||
};
|
||||
|
||||
struct PrintFlags
|
||||
{
|
||||
uint8_t scale;
|
||||
|
@ -97,8 +103,6 @@ struct PrintFlags
|
|||
#define PR_CJK_LOW (1 << 20) /* larger fonts should stick out fully on the bottom (draw at Y) */
|
||||
#define PR_CJK_HIGH (2 << 20) /* larger fonts should stick out fully on the top */
|
||||
|
||||
extern Font temp_bfont;
|
||||
|
||||
void load_main(void);
|
||||
void load_custom(void);
|
||||
void unload_custom(void);
|
||||
|
|
|
@ -1033,24 +1033,26 @@ void loadlanguagelist(void)
|
|||
// Load the list of languages for the language screen
|
||||
languagelist.clear();
|
||||
|
||||
std::vector<std::string> codes = FILESYSTEM_getLanguageCodes();
|
||||
size_t opt = 0;
|
||||
languagelist_curlang = 0;
|
||||
for (size_t i = 0; i < codes.size(); i++)
|
||||
EnumHandle handle = {};
|
||||
const char* code;
|
||||
while ((code = FILESYSTEM_enumerateLanguageCodes(&handle)) != NULL)
|
||||
{
|
||||
LangMeta meta;
|
||||
loadmeta(meta, codes[i]);
|
||||
loadmeta(meta, code);
|
||||
if (meta.active)
|
||||
{
|
||||
languagelist.push_back(meta);
|
||||
|
||||
if (lang == codes[i])
|
||||
if (SDL_strcmp(lang.c_str(), code) == 0)
|
||||
{
|
||||
languagelist_curlang = opt;
|
||||
}
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
FILESYSTEM_freeEnumerate(&handle);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue