Make language configurable in-game
This commit is contained in:
parent
30e802179b
commit
a9fe991ba4
|
@ -217,6 +217,7 @@ PAUSE_IN_SINGLEPLAYER = "Pause In Singleplayer"
|
|||
DISABLE_POPUPS = "Disable Popups"
|
||||
MENU_OPTIONS = "Menu Options"
|
||||
DEBUG = "Debug"
|
||||
LANGUAGE = "Language"
|
||||
|
||||
[MODLIST]
|
||||
MODS = "MODS"
|
||||
|
@ -312,3 +313,6 @@ MASTER_VOLUME = "Master Volume"
|
|||
MUSIC_VOLUME = "Music Volume"
|
||||
SFX_VOLUME = "Sfx Volume"
|
||||
ENV_VOLUME = "Env Volume"
|
||||
|
||||
[LANGUAGE]
|
||||
LANGUAGE = "LANGUAGE"
|
||||
|
|
|
@ -217,6 +217,7 @@ PAUSE_IN_SINGLEPLAYER = "Pausar en un jugador"
|
|||
DISABLE_POPUPS = "Desactivar ventanas emergentes"
|
||||
MENU_OPTIONS = "Opciones de menú"
|
||||
DEBUG = "Depurar"
|
||||
LANGUAGE = "Idioma"
|
||||
|
||||
[MODLIST]
|
||||
MODS = "MODS"
|
||||
|
@ -312,3 +313,6 @@ MASTER_VOLUME = "Volumen principal"
|
|||
MUSIC_VOLUME = "Volumen de la música"
|
||||
SFX_VOLUME = "Volumen SFX"
|
||||
ENV_VOLUME = "Volumen envolvente"
|
||||
|
||||
[LANGUAGE]
|
||||
LANGUAGE = "IDIOMA"
|
||||
|
|
|
@ -154,6 +154,7 @@ bool configSingleplayerPause = 0;
|
|||
bool configDebugPrint = 0;
|
||||
bool configDebugInfo = 0;
|
||||
bool configDebugError = 0;
|
||||
char configLanguage[MAX_CONFIG_STRING] = "";
|
||||
|
||||
static const struct ConfigOption options[] = {
|
||||
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen},
|
||||
|
@ -261,6 +262,7 @@ static const struct ConfigOption options[] = {
|
|||
{.name = "debug_print", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugPrint},
|
||||
{.name = "debug_info", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugInfo},
|
||||
{.name = "debug_error", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugError},
|
||||
{.name = "language", .type = CONFIG_TYPE_STRING, .stringValue = (char*)&configLanguage, .maxStringLength = MAX_CONFIG_STRING},
|
||||
};
|
||||
|
||||
// FunctionConfigOption functions
|
||||
|
|
|
@ -109,6 +109,7 @@ extern bool configSingleplayerPause;
|
|||
extern bool configDebugPrint;
|
||||
extern bool configDebugInfo;
|
||||
extern bool configDebugError;
|
||||
extern char configLanguage[];
|
||||
|
||||
void configfile_load(const char *filename);
|
||||
void configfile_save(const char *filename);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "djui.h"
|
||||
#include "djui_panel_language.h"
|
||||
#include "../debuglog.h"
|
||||
#include "pc/cliopts.h"
|
||||
#include "game/level_update.h"
|
||||
|
@ -62,6 +63,10 @@ void djui_init(void) {
|
|||
|
||||
if (gCLIOpts.Network != NT_SERVER) {
|
||||
djui_panel_main_create(NULL);
|
||||
if (configLanguage[0] == '\0') {
|
||||
gPanelLanguageOnStartup = true;
|
||||
djui_panel_language_create(NULL);
|
||||
}
|
||||
//djui_panel_debug_create();
|
||||
}
|
||||
djui_cursor_create();
|
||||
|
|
|
@ -22,6 +22,7 @@ static void djui_checkbox_update_style(struct DjuiBase* base) {
|
|||
djui_base_set_color(&checkbox->text->base, 200, 200, 200, 255);
|
||||
djui_base_set_color(&checkbox->rectValue->base, 200, 200, 200, 255);
|
||||
}
|
||||
djui_base_set_visible(&checkbox->rectValue->base, *checkbox->value);
|
||||
}
|
||||
|
||||
static void djui_checkbox_get_cursor_hover_location(struct DjuiBase* base, f32* x, f32* y) {
|
||||
|
|
|
@ -5,16 +5,28 @@
|
|||
|
||||
ini_t* sLang = NULL;
|
||||
|
||||
void djui_language_init(char* filename) {
|
||||
bool djui_language_init(char* lang) {
|
||||
// free old ini
|
||||
if (sLang != NULL) {
|
||||
ini_free(sLang);
|
||||
sLang = NULL;
|
||||
}
|
||||
|
||||
// construct path
|
||||
char path[SYS_MAX_PATH] = "";
|
||||
snprintf(path, SYS_MAX_PATH, "%s/lang/%s", sys_exe_path(), filename);
|
||||
if (!lang || lang[0] == '\0') { lang = "english"; }
|
||||
snprintf(path, SYS_MAX_PATH, "%s/lang/%s.ini", sys_exe_path(), lang);
|
||||
|
||||
// load
|
||||
sLang = ini_load(path);
|
||||
|
||||
return sLang != NULL;
|
||||
}
|
||||
|
||||
char* djui_language_get(const char *section, const char *key) {
|
||||
if (!sLang) { return "???"; }
|
||||
if (!sLang) { return (char*)key; }
|
||||
char* value = (char*)ini_get(sLang, section, key);
|
||||
if (!value) { return "???"; }
|
||||
if (!value) { return (char*)key; }
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#define DLANG(_SECTION, _KEY) djui_language_get(#_SECTION, #_KEY)
|
||||
|
||||
void djui_language_init(char* filename);
|
||||
bool djui_language_init(char* lang);
|
||||
char* djui_language_get(const char *section, const char *key);
|
||||
void djui_language_replace(char* src, char* dst, int size, char key, char* value);
|
||||
void djui_language_replace2(char* src, char* dst, int size, char key1, char* value1, char key2, char* value2);
|
||||
|
|
|
@ -144,12 +144,13 @@ void djui_panel_update(void) {
|
|||
djui_cursor_input_controlled_center(sPanelList->defaultElementBase);
|
||||
|
||||
if (removingBase != NULL) {
|
||||
if (sPanelRemoving->on_panel_destroy) {
|
||||
sPanelRemoving->on_panel_destroy(NULL);
|
||||
struct DjuiPanel* panel = sPanelRemoving;
|
||||
sPanelRemoving = NULL;
|
||||
if (panel->on_panel_destroy) {
|
||||
panel->on_panel_destroy(NULL);
|
||||
}
|
||||
djui_base_destroy(removingBase);
|
||||
free(sPanelRemoving);
|
||||
sPanelRemoving = NULL;
|
||||
free(panel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,6 +166,9 @@ void djui_panel_update(void) {
|
|||
}
|
||||
|
||||
void djui_panel_shutdown(void) {
|
||||
static bool sShuttingDown = false;
|
||||
if (sShuttingDown) { return; }
|
||||
sShuttingDown = true;
|
||||
struct DjuiPanel* panel = sPanelList;
|
||||
while (panel != NULL) {
|
||||
struct DjuiPanel* next = panel->parent;
|
||||
|
@ -177,11 +181,13 @@ void djui_panel_shutdown(void) {
|
|||
}
|
||||
|
||||
if (sPanelRemoving != NULL) {
|
||||
if (sPanelRemoving->on_panel_destroy) {
|
||||
sPanelRemoving->on_panel_destroy(NULL);
|
||||
struct DjuiPanel* panel = sPanelRemoving;
|
||||
sPanelRemoving = NULL;
|
||||
if (panel->on_panel_destroy) {
|
||||
panel->on_panel_destroy(NULL);
|
||||
}
|
||||
djui_base_destroy(sPanelRemoving->base);
|
||||
free(sPanelRemoving);
|
||||
djui_base_destroy(panel->base);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
sPanelList = NULL;
|
||||
|
@ -197,4 +203,5 @@ void djui_panel_shutdown(void) {
|
|||
gDjuiInMainMenu = false;
|
||||
newcam_init_settings();
|
||||
}
|
||||
sShuttingDown = false;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
#include "djui.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "pc/utils/misc.h"
|
||||
#include "pc/configfile.h"
|
||||
|
||||
extern bool directory_sanity_check(struct dirent* dir, char* dirPath, char* outPath);
|
||||
static bool sTrue = true;
|
||||
static bool sFalse = false;
|
||||
static bool sLanguageChanged = false;
|
||||
static struct DjuiBase* sLayoutBase = NULL;
|
||||
bool gPanelLanguageOnStartup = false;
|
||||
|
||||
static void select_language(struct DjuiBase* caller) {
|
||||
// god this is so hacky and terrible
|
||||
struct DjuiCheckbox* checkbox = (struct DjuiCheckbox*) caller;
|
||||
sTrue = true;
|
||||
sFalse = false;
|
||||
|
||||
struct DjuiBaseChild* child = sLayoutBase->child;
|
||||
while (child) {
|
||||
struct DjuiCheckbox* tmp = (struct DjuiCheckbox*)child->base;
|
||||
tmp->value = &sFalse;
|
||||
tmp->base.interactable->update_style(&tmp->base);
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (strcmp(configLanguage, checkbox->text->message)) {
|
||||
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", checkbox->text->message);
|
||||
sLanguageChanged = true;
|
||||
}
|
||||
|
||||
checkbox->value = &sTrue;
|
||||
checkbox->base.interactable->update_style(caller);
|
||||
}
|
||||
|
||||
static void djui_panel_language_destroy(UNUSED struct DjuiBase* caller) {
|
||||
// god this is so hacky and terrible
|
||||
if (sLanguageChanged) {
|
||||
sLanguageChanged = false;
|
||||
if (!djui_language_init(configLanguage)) {
|
||||
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", "");
|
||||
}
|
||||
|
||||
if (gPanelLanguageOnStartup) {
|
||||
djui_panel_shutdown();
|
||||
gDjuiInMainMenu = true;
|
||||
djui_panel_main_create(NULL);
|
||||
} else if (gDjuiInMainMenu) {
|
||||
djui_panel_shutdown();
|
||||
gDjuiInMainMenu = true;
|
||||
djui_panel_main_create(NULL);
|
||||
djui_panel_options_create(NULL);
|
||||
djui_panel_misc_create(NULL);
|
||||
} else if (gDjuiPanelPauseCreated) {
|
||||
djui_panel_shutdown();
|
||||
djui_panel_pause_create(NULL);
|
||||
djui_panel_options_create(NULL);
|
||||
djui_panel_misc_create(NULL);
|
||||
} else {
|
||||
djui_panel_shutdown();
|
||||
}
|
||||
}
|
||||
if (configLanguage[0] == '\0') {
|
||||
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", "english");
|
||||
}
|
||||
gPanelLanguageOnStartup = false;
|
||||
}
|
||||
|
||||
void djui_panel_language_create(struct DjuiBase* caller) {
|
||||
struct DjuiThreePanel* panel = djui_panel_menu_create(DLANG(LANGUAGE, LANGUAGE));
|
||||
struct DjuiBase* body = djui_three_panel_get_body(panel);
|
||||
sLanguageChanged = false;
|
||||
|
||||
{
|
||||
struct DjuiPaginated* paginated = djui_paginated_create(body, 8);
|
||||
sLayoutBase = &paginated->layout->base;
|
||||
|
||||
// construct lang path
|
||||
char lpath[SYS_MAX_PATH] = "";
|
||||
snprintf(lpath, SYS_MAX_PATH, "%s/lang", sys_exe_path());
|
||||
|
||||
// open directory
|
||||
struct dirent* dir = NULL;
|
||||
DIR* d = opendir(lpath);
|
||||
if (!d) {
|
||||
LOG_ERROR("Could not open directory '%s'", lpath);
|
||||
return;
|
||||
}
|
||||
|
||||
struct DjuiCheckbox* chkEnglish = NULL;
|
||||
bool foundMatch = false;
|
||||
|
||||
// iterate
|
||||
char path[SYS_MAX_PATH] = { 0 };
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
// sanity check / fill path[]
|
||||
if (!directory_sanity_check(dir, lpath, path)) { continue; }
|
||||
snprintf(path, SYS_MAX_PATH, "%s", dir->d_name);
|
||||
|
||||
// strip the name before the .
|
||||
char* c = path;
|
||||
while (*c != '\0') {
|
||||
if (*c == '.') { *c = '\0'; break;}
|
||||
c++;
|
||||
}
|
||||
if (strlen(path) == 0) { continue; }
|
||||
|
||||
bool match = !strcmp(path, configLanguage);
|
||||
if (match) { foundMatch = true; }
|
||||
struct DjuiCheckbox* checkbox = djui_checkbox_create(sLayoutBase, path, match ? &sTrue : &sFalse, select_language);
|
||||
if (!strcmp(path, "english")) { chkEnglish = checkbox; }
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (!foundMatch && chkEnglish) {
|
||||
chkEnglish->value = &sTrue;
|
||||
chkEnglish->base.interactable->update_style(&chkEnglish->base);
|
||||
}
|
||||
|
||||
djui_paginated_calculate_height(paginated);
|
||||
|
||||
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back);
|
||||
|
||||
panel->bodySize.value = paginated->base.height.value + 16 + 64;
|
||||
}
|
||||
|
||||
struct DjuiPanel* p = djui_panel_add(caller, panel, NULL);
|
||||
p->on_panel_destroy = djui_panel_language_destroy;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
#include "djui.h"
|
||||
|
||||
extern bool gPanelLanguageOnStartup;
|
||||
|
||||
void djui_panel_language_create(struct DjuiBase* caller);
|
|
@ -1,4 +1,5 @@
|
|||
#include "djui.h"
|
||||
#include "djui_panel_language.h"
|
||||
#include "src/pc/utils/misc.h"
|
||||
#include "src/pc/configfile.h"
|
||||
#include "game/hardcoded.h"
|
||||
|
@ -29,6 +30,7 @@ void djui_panel_misc_create(struct DjuiBase* caller) {
|
|||
{
|
||||
djui_checkbox_create(body, DLANG(MISC, PAUSE_IN_SINGLEPLAYER), &configSingleplayerPause, NULL);
|
||||
djui_checkbox_create(body, DLANG(MISC, DISABLE_POPUPS), &configDisablePopups, NULL);
|
||||
djui_button_create(body, DLANG(MISC, LANGUAGE), DJUI_BUTTON_STYLE_NORMAL, djui_panel_language_create);
|
||||
djui_button_create(body, DLANG(MISC, MENU_OPTIONS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_main_menu_create);
|
||||
#ifdef DEVELOPMENT
|
||||
djui_button_create(body, DLANG(MISC, DEBUG), DJUI_BUTTON_STYLE_NORMAL, djui_panel_options_debug_create);
|
||||
|
|
|
@ -273,11 +273,13 @@ void main_func(void) {
|
|||
const char *userpath = gCLIOpts.SavePath[0] ? gCLIOpts.SavePath : sys_user_path();
|
||||
fs_init(sys_ropaths, gamedir, userpath);
|
||||
|
||||
djui_language_init("english.ini");
|
||||
sync_objects_init_system();
|
||||
djui_unicode_init();
|
||||
mods_init();
|
||||
configfile_load(configfile_name());
|
||||
if (!djui_language_init(configLanguage)) {
|
||||
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", "");
|
||||
}
|
||||
dynos_pack_init();
|
||||
|
||||
// If coop_custom_palette_* values are not found in sm64config.txt, the custom palette config will use the default values (Mario's palette)
|
||||
|
|
Loading…
Reference in New Issue