mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Make language configurable in-game
This commit is contained in:
parent
30e802179b
commit
a9fe991ba4
13 changed files with 190 additions and 14 deletions
|
|
@ -217,6 +217,7 @@ PAUSE_IN_SINGLEPLAYER = "Pause In Singleplayer"
|
||||||
DISABLE_POPUPS = "Disable Popups"
|
DISABLE_POPUPS = "Disable Popups"
|
||||||
MENU_OPTIONS = "Menu Options"
|
MENU_OPTIONS = "Menu Options"
|
||||||
DEBUG = "Debug"
|
DEBUG = "Debug"
|
||||||
|
LANGUAGE = "Language"
|
||||||
|
|
||||||
[MODLIST]
|
[MODLIST]
|
||||||
MODS = "MODS"
|
MODS = "MODS"
|
||||||
|
|
@ -312,3 +313,6 @@ MASTER_VOLUME = "Master Volume"
|
||||||
MUSIC_VOLUME = "Music Volume"
|
MUSIC_VOLUME = "Music Volume"
|
||||||
SFX_VOLUME = "Sfx Volume"
|
SFX_VOLUME = "Sfx Volume"
|
||||||
ENV_VOLUME = "Env Volume"
|
ENV_VOLUME = "Env Volume"
|
||||||
|
|
||||||
|
[LANGUAGE]
|
||||||
|
LANGUAGE = "LANGUAGE"
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ PAUSE_IN_SINGLEPLAYER = "Pausar en un jugador"
|
||||||
DISABLE_POPUPS = "Desactivar ventanas emergentes"
|
DISABLE_POPUPS = "Desactivar ventanas emergentes"
|
||||||
MENU_OPTIONS = "Opciones de menú"
|
MENU_OPTIONS = "Opciones de menú"
|
||||||
DEBUG = "Depurar"
|
DEBUG = "Depurar"
|
||||||
|
LANGUAGE = "Idioma"
|
||||||
|
|
||||||
[MODLIST]
|
[MODLIST]
|
||||||
MODS = "MODS"
|
MODS = "MODS"
|
||||||
|
|
@ -312,3 +313,6 @@ MASTER_VOLUME = "Volumen principal"
|
||||||
MUSIC_VOLUME = "Volumen de la música"
|
MUSIC_VOLUME = "Volumen de la música"
|
||||||
SFX_VOLUME = "Volumen SFX"
|
SFX_VOLUME = "Volumen SFX"
|
||||||
ENV_VOLUME = "Volumen envolvente"
|
ENV_VOLUME = "Volumen envolvente"
|
||||||
|
|
||||||
|
[LANGUAGE]
|
||||||
|
LANGUAGE = "IDIOMA"
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,7 @@ bool configSingleplayerPause = 0;
|
||||||
bool configDebugPrint = 0;
|
bool configDebugPrint = 0;
|
||||||
bool configDebugInfo = 0;
|
bool configDebugInfo = 0;
|
||||||
bool configDebugError = 0;
|
bool configDebugError = 0;
|
||||||
|
char configLanguage[MAX_CONFIG_STRING] = "";
|
||||||
|
|
||||||
static const struct ConfigOption options[] = {
|
static const struct ConfigOption options[] = {
|
||||||
{.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen},
|
{.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_print", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugPrint},
|
||||||
{.name = "debug_info", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugInfo},
|
{.name = "debug_info", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugInfo},
|
||||||
{.name = "debug_error", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugError},
|
{.name = "debug_error", .type = CONFIG_TYPE_BOOL , .boolValue = &configDebugError},
|
||||||
|
{.name = "language", .type = CONFIG_TYPE_STRING, .stringValue = (char*)&configLanguage, .maxStringLength = MAX_CONFIG_STRING},
|
||||||
};
|
};
|
||||||
|
|
||||||
// FunctionConfigOption functions
|
// FunctionConfigOption functions
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ extern bool configSingleplayerPause;
|
||||||
extern bool configDebugPrint;
|
extern bool configDebugPrint;
|
||||||
extern bool configDebugInfo;
|
extern bool configDebugInfo;
|
||||||
extern bool configDebugError;
|
extern bool configDebugError;
|
||||||
|
extern char configLanguage[];
|
||||||
|
|
||||||
void configfile_load(const char *filename);
|
void configfile_load(const char *filename);
|
||||||
void configfile_save(const char *filename);
|
void configfile_save(const char *filename);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "djui.h"
|
#include "djui.h"
|
||||||
|
#include "djui_panel_language.h"
|
||||||
#include "../debuglog.h"
|
#include "../debuglog.h"
|
||||||
#include "pc/cliopts.h"
|
#include "pc/cliopts.h"
|
||||||
#include "game/level_update.h"
|
#include "game/level_update.h"
|
||||||
|
|
@ -62,6 +63,10 @@ void djui_init(void) {
|
||||||
|
|
||||||
if (gCLIOpts.Network != NT_SERVER) {
|
if (gCLIOpts.Network != NT_SERVER) {
|
||||||
djui_panel_main_create(NULL);
|
djui_panel_main_create(NULL);
|
||||||
|
if (configLanguage[0] == '\0') {
|
||||||
|
gPanelLanguageOnStartup = true;
|
||||||
|
djui_panel_language_create(NULL);
|
||||||
|
}
|
||||||
//djui_panel_debug_create();
|
//djui_panel_debug_create();
|
||||||
}
|
}
|
||||||
djui_cursor_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->text->base, 200, 200, 200, 255);
|
||||||
djui_base_set_color(&checkbox->rectValue->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) {
|
static void djui_checkbox_get_cursor_hover_location(struct DjuiBase* base, f32* x, f32* y) {
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,28 @@
|
||||||
|
|
||||||
ini_t* sLang = NULL;
|
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] = "";
|
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);
|
sLang = ini_load(path);
|
||||||
|
|
||||||
|
return sLang != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* djui_language_get(const char *section, const char *key) {
|
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);
|
char* value = (char*)ini_get(sLang, section, key);
|
||||||
if (!value) { return "???"; }
|
if (!value) { return (char*)key; }
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#define DLANG(_SECTION, _KEY) djui_language_get(#_SECTION, #_KEY)
|
#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);
|
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_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);
|
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);
|
djui_cursor_input_controlled_center(sPanelList->defaultElementBase);
|
||||||
|
|
||||||
if (removingBase != NULL) {
|
if (removingBase != NULL) {
|
||||||
if (sPanelRemoving->on_panel_destroy) {
|
struct DjuiPanel* panel = sPanelRemoving;
|
||||||
sPanelRemoving->on_panel_destroy(NULL);
|
sPanelRemoving = NULL;
|
||||||
|
if (panel->on_panel_destroy) {
|
||||||
|
panel->on_panel_destroy(NULL);
|
||||||
}
|
}
|
||||||
djui_base_destroy(removingBase);
|
djui_base_destroy(removingBase);
|
||||||
free(sPanelRemoving);
|
free(panel);
|
||||||
sPanelRemoving = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,6 +166,9 @@ void djui_panel_update(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void djui_panel_shutdown(void) {
|
void djui_panel_shutdown(void) {
|
||||||
|
static bool sShuttingDown = false;
|
||||||
|
if (sShuttingDown) { return; }
|
||||||
|
sShuttingDown = true;
|
||||||
struct DjuiPanel* panel = sPanelList;
|
struct DjuiPanel* panel = sPanelList;
|
||||||
while (panel != NULL) {
|
while (panel != NULL) {
|
||||||
struct DjuiPanel* next = panel->parent;
|
struct DjuiPanel* next = panel->parent;
|
||||||
|
|
@ -177,11 +181,13 @@ void djui_panel_shutdown(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sPanelRemoving != NULL) {
|
if (sPanelRemoving != NULL) {
|
||||||
if (sPanelRemoving->on_panel_destroy) {
|
struct DjuiPanel* panel = sPanelRemoving;
|
||||||
sPanelRemoving->on_panel_destroy(NULL);
|
sPanelRemoving = NULL;
|
||||||
|
if (panel->on_panel_destroy) {
|
||||||
|
panel->on_panel_destroy(NULL);
|
||||||
}
|
}
|
||||||
djui_base_destroy(sPanelRemoving->base);
|
djui_base_destroy(panel->base);
|
||||||
free(sPanelRemoving);
|
free(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
sPanelList = NULL;
|
sPanelList = NULL;
|
||||||
|
|
@ -197,4 +203,5 @@ void djui_panel_shutdown(void) {
|
||||||
gDjuiInMainMenu = false;
|
gDjuiInMainMenu = false;
|
||||||
newcam_init_settings();
|
newcam_init_settings();
|
||||||
}
|
}
|
||||||
|
sShuttingDown = false;
|
||||||
}
|
}
|
||||||
130
src/pc/djui/djui_panel_language.c
Normal file
130
src/pc/djui/djui_panel_language.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
6
src/pc/djui/djui_panel_language.h
Normal file
6
src/pc/djui/djui_panel_language.h
Normal file
|
|
@ -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.h"
|
||||||
|
#include "djui_panel_language.h"
|
||||||
#include "src/pc/utils/misc.h"
|
#include "src/pc/utils/misc.h"
|
||||||
#include "src/pc/configfile.h"
|
#include "src/pc/configfile.h"
|
||||||
#include "game/hardcoded.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, PAUSE_IN_SINGLEPLAYER), &configSingleplayerPause, NULL);
|
||||||
djui_checkbox_create(body, DLANG(MISC, DISABLE_POPUPS), &configDisablePopups, 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);
|
djui_button_create(body, DLANG(MISC, MENU_OPTIONS), DJUI_BUTTON_STYLE_NORMAL, djui_panel_main_menu_create);
|
||||||
#ifdef DEVELOPMENT
|
#ifdef DEVELOPMENT
|
||||||
djui_button_create(body, DLANG(MISC, DEBUG), DJUI_BUTTON_STYLE_NORMAL, djui_panel_options_debug_create);
|
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();
|
const char *userpath = gCLIOpts.SavePath[0] ? gCLIOpts.SavePath : sys_user_path();
|
||||||
fs_init(sys_ropaths, gamedir, userpath);
|
fs_init(sys_ropaths, gamedir, userpath);
|
||||||
|
|
||||||
djui_language_init("english.ini");
|
|
||||||
sync_objects_init_system();
|
sync_objects_init_system();
|
||||||
djui_unicode_init();
|
djui_unicode_init();
|
||||||
mods_init();
|
mods_init();
|
||||||
configfile_load(configfile_name());
|
configfile_load(configfile_name());
|
||||||
|
if (!djui_language_init(configLanguage)) {
|
||||||
|
snprintf(configLanguage, MAX_CONFIG_STRING, "%s", "");
|
||||||
|
}
|
||||||
dynos_pack_init();
|
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)
|
// If coop_custom_palette_* values are not found in sm64config.txt, the custom palette config will use the default values (Mario's palette)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue