From eab0c6fc4fe9d12033b38dba795ea149bf95184a Mon Sep 17 00:00:00 2001 From: tsht Date: Sun, 5 May 2024 09:10:07 +0200 Subject: [PATCH 1/4] Theme selection --- src/gui/gui2_canvas.cpp | 3 +- src/gui/theme.cpp | 10 ++++- src/main.cpp | 20 ++++++--- src/menus/optionsMenu.cpp | 87 ++++++++++++++++++++++++++++++--------- 4 files changed, 91 insertions(+), 29 deletions(-) diff --git a/src/gui/gui2_canvas.cpp b/src/gui/gui2_canvas.cpp index 5bcc0c4833..c91d7bae9d 100644 --- a/src/gui/gui2_canvas.cpp +++ b/src/gui/gui2_canvas.cpp @@ -1,13 +1,14 @@ #include "gui2_canvas.h" #include "gui2_element.h" #include "theme.h" +#include "preferenceManager.h" GuiCanvas::GuiCanvas(RenderLayer* renderLayer) : Renderable(renderLayer), click_element(nullptr), focus_element(nullptr) { enable_debug_rendering = false; - theme = GuiTheme::getTheme("default"); + theme = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default")); //Should be fast as PreferenceManager is cached } //due to a suspected compiler bug this deconstructor needs to be explicitly defined diff --git a/src/gui/theme.cpp b/src/gui/theme.cpp index 3b0d0fa887..9d8cb94771 100644 --- a/src/gui/theme.cpp +++ b/src/gui/theme.cpp @@ -1,4 +1,5 @@ #include "gui/theme.h" +#include "resources.h" #include #include #include @@ -44,7 +45,7 @@ const GuiThemeStyle* GuiTheme::getStyle(const string& element) int n = element.rfind("."); if (n == -1) { - LOG(Warning, "Cannot find", element, "in theme", name); + LOG(Warning, "Cannot find ", element, " in theme ", name); return getStyle("fallback"); } return getStyle(element.substr(0, n)); @@ -60,7 +61,7 @@ GuiTheme* GuiTheme::getTheme(const string& name) LOG(Error, "Default theme not found. Most likely crashing now."); return nullptr; } - LOG(Warning, "Theme", name, "not found. Falling back to [default] theme."); + LOG(Warning, "Theme ", name, " not found. Falling back to [default] theme."); return getTheme("default"); } @@ -133,6 +134,11 @@ GuiTheme::GuiTheme(const string& name) fallback_state.color = {255, 255, 255, 255}; fallback_state.size = 12; fallback_state.font = nullptr; + std::vector fonts = findResources("gui/fonts/*.ttf"); + if(fonts.size() > 0) + { + fallback_state.font = getFont(fonts[0]); + } fallback_state.texture = ""; GuiThemeStyle fallback; for(unsigned int n=0; nsetMusicVolume(PreferencesManager::get("music_volume", "50").toFloat()); soundManager->setMasterSoundVolume(PreferencesManager::get("sound_volume", "50").toFloat()); - main_font = GuiTheme::getTheme("default")->getStyle("base")->states[0].font; - bold_font = GuiTheme::getTheme("default")->getStyle("bold")->states[0].font; + main_font = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default"))->getStyle("base")->states[0].font; + bold_font = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default"))->getStyle("bold")->states[0].font; if (!main_font || !bold_font) { LOG(ERROR, "Missing font or bold font."); diff --git a/src/menus/optionsMenu.cpp b/src/menus/optionsMenu.cpp index 17d8cea4e4..5546986da6 100644 --- a/src/menus/optionsMenu.cpp +++ b/src/menus/optionsMenu.cpp @@ -7,6 +7,7 @@ #include "soundManager.h" #include "windowManager.h" +#include "gui/theme.h" #include "gui/gui2_overlay.h" #include "gui/gui2_button.h" #include "gui/gui2_togglebutton.h" @@ -104,31 +105,77 @@ OptionsMenu::OptionsMenu() }))->setSize(GuiElement::GuiSizeMax, 50); //Select the language - (new GuiLabel(interface_page, "LANGUAGE_OPTIONS_LABEL", tr("Language (applies on back)"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20; - - std::vector languages = findResources("locale/main.*.po"); - - for(string &language : languages) { - //strip extension - language = language.substr(language.find(".") + 1, language.rfind(".")); - } - std::sort(languages.begin(), languages.end()); + (new GuiLabel(interface_page, "LANGUAGE_OPTIONS_LABEL", tr("Language (applies on back)"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20; + + std::vector languages = findResources("locale/main.*.po"); + + for(string &language : languages) + { + //strip extension + language = language.substr(language.find(".") + 1, language.rfind(".")); + } + std::sort(languages.begin(), languages.end()); - int default_index = 0; - auto default_elem = std::find(languages.begin(), languages.end(), PreferencesManager::get("language", "en")); - if(default_elem != languages.end()) - { - default_index = static_cast(default_elem - languages.begin()); + int default_index = 0; + auto default_elem = std::find(languages.begin(), languages.end(), PreferencesManager::get("language", "en")); + if(default_elem != languages.end()) + { + default_index = static_cast(default_elem - languages.begin()); + } + + (new GuiSelector(interface_page, "LANGUAGE_SELECTOR", [](int index, string value) + { + i18n::reset(); + i18n::load("locale/main." + value + ".po"); + PreferencesManager::set("language", value); + keys.init(); // Reinit keyboard shortcut labels + }))->setOptions(languages)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50); } - (new GuiSelector(interface_page, "LANGUAGE_SELECTOR", [](int index, string value) + //Gui theme selection { - i18n::reset(); - i18n::load("locale/main." + value + ".po"); - PreferencesManager::set("language", value); - keys.init(); // Reinit keyboard shortcut labels - }))->setOptions(languages)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50); + (new GuiLabel(interface_page, "GUI_THEME_OPTIONS_LABEL", tr("Interface Theme"), 30))->addBackground()->setSize(GuiElement::GuiSizeMax, 50)->layout.margin.top = 20; + + std::vector themes = findResources("gui/*.theme.txt"); + + auto iter = themes.begin(); + while(iter != themes.end()) + { + //strip extension + *iter = iter->substr(iter->find("/")+1, iter->find(".")); + if (!GuiTheme::loadTheme(*iter, "gui/" + *iter +".theme.txt")) + { + LOG(ERROR, "Failed to load theme : ", *iter); + iter = themes.erase(iter); + } + else + { + ++iter; + } + } + + std::sort(themes.begin(), themes.end()); + if(0 == themes.size()) + { + LOG(ERROR, "Failed to load any theme, exiting"); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to load any theme, resources missing ? Should be gui/*.theme.txt. and not contain errors.", nullptr); + exit(1); + } + + int default_index = 0; + auto default_elem = std::find(themes.begin(), themes.end(), PreferencesManager::get("guitheme", "default")); + if(default_elem != themes.end()) + { + default_index = static_cast(default_elem - themes.begin()); + } + + (new GuiSelector(interface_page, "GUI_THEME_SELECTOR", [](int index, string theme_name) + { + LOG(INFO, "Set theme to : ", theme_name); + PreferencesManager::set("guitheme", theme_name); + }))->setOptions(themes)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50); + } // Bottom GUI. // Back button. From 4d9333154f82fdeac4b5d79f8be6829a0d372e91 Mon Sep 17 00:00:00 2001 From: tsht Date: Mon, 6 May 2024 08:58:41 +0200 Subject: [PATCH 2/4] Remove dependency from canvas to preference manager, tradoff by static member --- src/gui/gui2_canvas.cpp | 4 +--- src/gui/theme.cpp | 15 +++++++++++++++ src/gui/theme.h | 4 ++++ src/main.cpp | 7 +++++-- src/menus/optionsMenu.cpp | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/gui/gui2_canvas.cpp b/src/gui/gui2_canvas.cpp index c91d7bae9d..be6cb1a16c 100644 --- a/src/gui/gui2_canvas.cpp +++ b/src/gui/gui2_canvas.cpp @@ -1,14 +1,12 @@ #include "gui2_canvas.h" #include "gui2_element.h" #include "theme.h" -#include "preferenceManager.h" - GuiCanvas::GuiCanvas(RenderLayer* renderLayer) : Renderable(renderLayer), click_element(nullptr), focus_element(nullptr) { enable_debug_rendering = false; - theme = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default")); //Should be fast as PreferenceManager is cached + theme = GuiTheme::getCurrentTheme(); } //due to a suspected compiler bug this deconstructor needs to be explicitly defined diff --git a/src/gui/theme.cpp b/src/gui/theme.cpp index 9d8cb94771..837f3da19e 100644 --- a/src/gui/theme.cpp +++ b/src/gui/theme.cpp @@ -7,6 +7,7 @@ static std::unordered_map fonts; std::unordered_map GuiTheme::themes; +string GuiTheme::current_theme = "default"; static glm::u8vec4 toColor(const string& s) { @@ -65,6 +66,20 @@ GuiTheme* GuiTheme::getTheme(const string& name) return getTheme("default"); } +void GuiTheme::setCurrentTheme(const string &theme_name) +{ + if(themes.find(theme_name) != themes.end()) + { + LOG(INFO, "Set theme to : ", theme_name); + GuiTheme::current_theme = theme_name; + } +} + +GuiTheme* GuiTheme::getCurrentTheme() +{ + return GuiTheme::getTheme(GuiTheme::current_theme); +} + bool GuiTheme::loadTheme(const string& name, const string& resource_name) { GuiTheme* theme = new GuiTheme(name); diff --git a/src/gui/theme.h b/src/gui/theme.h index 676f7e4b6a..cd43226fea 100644 --- a/src/gui/theme.h +++ b/src/gui/theme.h @@ -46,6 +46,9 @@ class GuiTheme const GuiThemeStyle* getStyle(const string& element); static GuiTheme* getTheme(const string& name); + //Will return default theme if not found + static GuiTheme* getCurrentTheme(); + static void setCurrentTheme(const string &name); static bool loadTheme(const string& name, const string& resource_name); private: GuiTheme(const string& name); @@ -55,6 +58,7 @@ class GuiTheme std::unordered_map styles; static std::unordered_map themes; + static string current_theme; }; #endif//GUI_THEME_H diff --git a/src/main.cpp b/src/main.cpp index 8b86826f47..7fcc5c523d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -244,8 +244,11 @@ int main(int argc, char** argv) SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to load gui theme, resources missing or contains errors ? Check gui/default.theme.txt", nullptr); return 1; } - LOG(INFO, "Set theme to : default."); - PreferencesManager::set("guitheme", "default"); + GuiTheme::setCurrentTheme("default"); + } + else + { + GuiTheme::setCurrentTheme(theme_name); } if (PreferencesManager::get("headless") == "") diff --git a/src/menus/optionsMenu.cpp b/src/menus/optionsMenu.cpp index 6d1ea55063..c9814575f3 100644 --- a/src/menus/optionsMenu.cpp +++ b/src/menus/optionsMenu.cpp @@ -172,8 +172,8 @@ OptionsMenu::OptionsMenu() (new GuiSelector(interface_page, "GUI_THEME_SELECTOR", [](int index, string theme_name) { - LOG(INFO, "Set theme to : ", theme_name); PreferencesManager::set("guitheme", theme_name); + GuiTheme::setCurrentTheme(theme_name); }))->setOptions(themes)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50); } From 63cb15dca480b7f88efda9fb4b1c5e0ead420408 Mon Sep 17 00:00:00 2001 From: tsht Date: Mon, 6 May 2024 09:06:48 +0200 Subject: [PATCH 3/4] Forgotten occurrence in main --- src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 7fcc5c523d..993502a05e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -343,8 +343,8 @@ int main(int argc, char** argv) soundManager->setMusicVolume(PreferencesManager::get("music_volume", "50").toFloat()); soundManager->setMasterSoundVolume(PreferencesManager::get("sound_volume", "50").toFloat()); - main_font = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default"))->getStyle("base")->states[0].font; - bold_font = GuiTheme::getTheme(PreferencesManager::get("guitheme", "default"))->getStyle("bold")->states[0].font; + main_font = GuiTheme::getCurrentTheme()->getStyle("base")->states[0].font; + bold_font = GuiTheme::getCurrentTheme()->getStyle("bold")->states[0].font; if (!main_font || !bold_font) { LOG(ERROR, "Missing font or bold font."); From 4e570706639ffbee828fa8eab50887e15b820051 Mon Sep 17 00:00:00 2001 From: tsht Date: Mon, 6 May 2024 23:00:31 +0200 Subject: [PATCH 4/4] Change font when changing theme --- src/menus/optionsMenu.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/menus/optionsMenu.cpp b/src/menus/optionsMenu.cpp index c9814575f3..28f751c35e 100644 --- a/src/menus/optionsMenu.cpp +++ b/src/menus/optionsMenu.cpp @@ -149,6 +149,12 @@ OptionsMenu::OptionsMenu() LOG(ERROR, "Failed to load theme : ", *iter); iter = themes.erase(iter); } + else if (!GuiTheme::getTheme(*iter)->getStyle("base")->states[0].font + || !GuiTheme::getTheme(*iter)->getStyle("bold")->states[0].font) + { + LOG(ERROR, "Missing base font or bold font for theme : ", *iter); + iter = themes.erase(iter); + } else { ++iter; @@ -172,8 +178,11 @@ OptionsMenu::OptionsMenu() (new GuiSelector(interface_page, "GUI_THEME_SELECTOR", [](int index, string theme_name) { - PreferencesManager::set("guitheme", theme_name); GuiTheme::setCurrentTheme(theme_name); + main_font = GuiTheme::getCurrentTheme()->getStyle("base")->states[0].font; + bold_font = GuiTheme::getCurrentTheme()->getStyle("bold")->states[0].font; + //Render default font is applied on back only + PreferencesManager::set("guitheme", theme_name); }))->setOptions(themes)->setSelectionIndex(default_index)->setSize(GuiElement::GuiSizeMax, 50); } @@ -181,6 +190,8 @@ OptionsMenu::OptionsMenu() // Back button. (new GuiButton(this, "BACK", tr("button", "Back"), [this]() { + //Apply potentially modified font now, in order not to have some half rendered panel with one font and another + sp::RenderTarget::setDefaultFont(main_font); // Close this menu, stop the music, and return to the main menu. destroy(); soundManager->stopMusic();