diff --git a/src/frontend/Language.cpp b/src/frontend/Language.cpp new file mode 100644 index 00000000..4b5481b8 --- /dev/null +++ b/src/frontend/Language.cpp @@ -0,0 +1,11 @@ +#include + +namespace Language { +void SetLanguage(const std::array& lang, int selectedLang) { + switch (selectedLang) { + case AvailableLangs::ENGLISH: std::copy(english.begin(), english.end(), lang.begin()); break; + case AvailableLangs::ITALIAN: std::copy(italian.begin(), italian.end(), lang.begin()); break; + default: Util::panic("Language not supported, index {}\n", selectedLang); + } +} +} \ No newline at end of file diff --git a/src/frontend/Language.hpp b/src/frontend/Language.hpp new file mode 100644 index 00000000..c8fee815 --- /dev/null +++ b/src/frontend/Language.hpp @@ -0,0 +1,85 @@ +#pragma once +#include +#include + +namespace Language { + +enum StringID { + MENU_FILE, + FILE_ITEM_OPEN, + FILE_ITEM_EXIT, + MENU_EMULATION, + EMULATION_ITEM_RESET, + EMULATION_ITEM_STOP, + EMULATION_ITEM_PAUSE, + EMULATION_ITEM_RESUME, + EMULATION_ITEM_SETTINGS, + SETTINGS_CATEGORY_CPU, + SETTINGS_CATEGORY_AUDIO, + SETTINGS_CATEGORY_INTERFACE, + SETTINGS_OPTION_MUTE, + SETTINGS_OPTION_VOLUME_L, + SETTINGS_OPTION_VOLUME_R, + SETTINGS_OPTION_LOCK_CHANNELS, + SETTINGS_OPTION_ENABLE_JIT, + SETTINGS_OPTION_LANGUAGE, + LANGUAGE_ENGLISH, + LANGUAGE_ITALIAN, + STRING_COUNT +}; + +static const std::array english = { + "File", + "Open", + "Exit", + "Emulation", + "Reset", + "Stop", + "Pause", + "Resume", + "Settings", + "CPU", + "Audio", + "Interface", + "Mute", + "Volume L", + "Volume R", + "Lock channels", + "Enable JIT", + "Language" +}; + +static const std::array italian = { + "File", + "Apri", + "Esci", + "Emulazione", + "Reset", + "Stop", + "Pausa", + "Riprendi", + "Impostazioni", + "CPU", + "Audio", + "Interfaccia", + "Muto", + "Volume L", + "Volume R", + "Blocca canali", + "Abilita JIT", + "Lingua" +}; + +enum AvailableLangs { + ENGLISH, + ITALIAN, + AVAILABLE_LANGS_COUNT +}; + +static const std::array languages = { + "English", + "Italiano" +}; + +void SetLanguage(const std::array& lang, int selectedLang); +} \ No newline at end of file diff --git a/src/frontend/imgui/Settings.cpp b/src/frontend/imgui/Settings.cpp index f57117b7..1a8432db 100644 --- a/src/frontend/imgui/Settings.cpp +++ b/src/frontend/imgui/Settings.cpp @@ -6,7 +6,7 @@ namespace fs = std::filesystem; -#define checkjsonentry(name, type, param1, param2, defaultVal) \ +#define checknestedjsonentry(name, type, param1, param2, defaultVal) \ do { \ auto name##Entry = settings[param1][param2]; \ if(!name##Entry.empty()) { \ @@ -20,6 +20,20 @@ namespace fs = std::filesystem; } \ } while(0) +#define checkjsonentry(name, type, param, defaultVal) \ + do { \ + auto name##Entry = settings[param]; \ + if(!name##Entry.empty()) { \ + auto value = name##Entry.get(); \ + (name) = value; \ + } else { \ + settingsFile.clear(); \ + settings[param] = defaultVal; \ + settingsFile << settings; \ + (name) = defaultVal; \ + } \ + } while(0) + Settings::Settings(n64::Core& core) { auto fileExists = fs::exists("resources/settings.json"); @@ -28,13 +42,14 @@ Settings::Settings(n64::Core& core) { settingsFile = std::fstream("resources/settings.json", std::fstream::in | std::fstream::out); settings = json::parse(settingsFile); - checkjsonentry(oldVolumeL, float, "audio", "volumeL", 0.5); - checkjsonentry(oldVolumeR, float, "audio", "volumeR", 0.5); - checkjsonentry(mute, bool, "audio", "mute", false); + checknestedjsonentry(oldVolumeL, float, "audio", "volumeL", 0.5); + checknestedjsonentry(oldVolumeR, float, "audio", "volumeR", 0.5); + checknestedjsonentry(mute, bool, "audio", "mute", false); volumeL = mute ? 0 : oldVolumeL; volumeR = mute ? 0 : oldVolumeR; - checkjsonentry(lockChannels, bool, "audio", "lockChannels", true); - checkjsonentry(jit, bool, "cpu", "enableJIT", false); + checknestedjsonentry(lockChannels, bool, "audio", "lockChannels", true); + checknestedjsonentry(jit, bool, "cpu", "enableJIT", false); + checkjsonentry(selectedLanguage, int, "language", Language::ENGLISH); } else { settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::in | std::fstream::out); settings["audio"]["volumeR"] = 0.5; @@ -42,6 +57,7 @@ Settings::Settings(n64::Core& core) { settings["audio"]["lockChannels"] = true; settings["audio"]["mute"] = false; settings["cpu"]["enableJIT"] = false; + settings["language"] = Language::ENGLISH; oldVolumeR = volumeR = 0.5; oldVolumeL = volumeL = 0.5; @@ -52,6 +68,8 @@ Settings::Settings(n64::Core& core) { settingsFile << settings; } + Language::SetLanguage(languageStrings, selectedLanguage); + if(jit) { core.cpu = std::make_unique(); } else { @@ -74,6 +92,7 @@ Settings::~Settings() { settings["audio"]["lockChannels"] = lockChannels; settings["audio"]["mute"] = mute; settings["cpu"]["enableJIT"] = jit; + settings["language"] = selectedLanguage; settingsFile << settings; settingsFile.close(); @@ -82,38 +101,44 @@ Settings::~Settings() { void Settings::RenderWidget(bool& show) { if(show) { ImGui::OpenPopup("Settings"); - if(ImGui::BeginPopupModal("Settings", &show)) { - enum class SelectedSetting { CPU, Audio, COUNT }; + if(ImGui::BeginPopupModal(languageStrings[Language::EMULATION_ITEM_SETTINGS].c_str(), &show)) { + enum class SelectedSetting { CPU, Audio, Interface, COUNT }; static SelectedSetting selectedSetting = SelectedSetting::CPU; - const char *categories[(int)SelectedSetting::COUNT] = { "CPU", "Audio" }; + const char *categories[(int)SelectedSetting::COUNT] = { + languageStrings[Language::SETTINGS_CATEGORY_CPU].c_str(), + languageStrings[Language::SETTINGS_CATEGORY_AUDIO].c_str(), + languageStrings[Language::SETTINGS_CATEGORY_INTERFACE].c_str() }; + CreateComboList("##", (int*)&selectedSetting, categories, (int)SelectedSetting::COUNT); ImGui::Separator(); switch (selectedSetting) { case SelectedSetting::Audio: - ImGui::Checkbox("Lock channels", &lockChannels); - ImGui::Checkbox("Mute", &mute); + ImGui::Checkbox(languageStrings[Language::SETTINGS_OPTION_LOCK_CHANNELS].c_str(), &lockChannels); + ImGui::Checkbox(languageStrings[Language::SETTINGS_OPTION_MUTE].c_str(), &mute); if(mute) { volumeL = 0; volumeR = 0; ImGui::BeginDisabled(); - ImGui::SliderFloat("Volume L", &oldVolumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); + ImGui::SliderFloat(languageStrings[Language::SETTINGS_OPTION_VOLUME_L].c_str(), &oldVolumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); if (lockChannels) { oldVolumeR = oldVolumeL; } - ImGui::SliderFloat("Volume R", &oldVolumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); + ImGui::SliderFloat(languageStrings[Language::SETTINGS_OPTION_VOLUME_R].c_str(), &oldVolumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); ImGui::EndDisabled(); - } else { + } + else { volumeL = oldVolumeL; volumeR = oldVolumeR; - ImGui::SliderFloat("Volume L", &volumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); + ImGui::SliderFloat(languageStrings[Language::SETTINGS_OPTION_VOLUME_L].c_str(), &volumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); if (!lockChannels) { - ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); - } else { + ImGui::SliderFloat(languageStrings[Language::SETTINGS_OPTION_VOLUME_R].c_str(), &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); + } + else { volumeR = volumeL; ImGui::BeginDisabled(); - ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); + ImGui::SliderFloat(languageStrings[Language::SETTINGS_OPTION_VOLUME_R].c_str(), &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput); ImGui::EndDisabled(); } @@ -123,8 +148,15 @@ void Settings::RenderWidget(bool& show) { break; case SelectedSetting::CPU: - ImGui::Checkbox("Enable JIT", &jit); + ImGui::Checkbox(languageStrings[Language::SETTINGS_OPTION_ENABLE_JIT].c_str(), &jit); break; + case SelectedSetting::Interface: { + const char* languages[Language::AVAILABLE_LANGS_COUNT] = { + Language::languages[0].c_str(), + Language::languages[1].c_str() + }; + CreateComboList("##", &selectedLanguage, languages, Language::AVAILABLE_LANGS_COUNT); + } break; case SelectedSetting::COUNT: Util::panic("BRUH"); } diff --git a/src/frontend/imgui/Settings.hpp b/src/frontend/imgui/Settings.hpp index bbe24bb6..848cbe35 100644 --- a/src/frontend/imgui/Settings.hpp +++ b/src/frontend/imgui/Settings.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace n64 { struct Core; } using namespace nlohmann; @@ -19,5 +19,7 @@ private: float oldVolumeL, oldVolumeR; bool lockChannels = true; bool mute = false; + int selectedLanguage = Language::ENGLISH; + std::array languageStrings{}; json settings; }; diff --git a/src/frontend/imgui/Window.cpp b/src/frontend/imgui/Window.cpp index 8a882b90..71e8a33c 100644 --- a/src/frontend/imgui/Window.cpp +++ b/src/frontend/imgui/Window.cpp @@ -16,11 +16,11 @@ Window::Window(n64::Core& core) : settings(core) { } void Window::handleEvents(SDL_Event event, n64::Core& core) { - done = event.window.event == SDL_WINDOWEVENT_CLOSE + done = event.window.event == (int)SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window); bool minimized = SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED; - core.pause = event.window.event == SDL_WINDOWEVENT_FOCUS_LOST || minimized; + core.pause = event.window.event == (int)SDL_WINDOWEVENT_FOCUS_LOST || minimized; core.render = !minimized; }