From 08eac606573429d24aacc87a6adad86012d8584e Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Tue, 7 Jul 2026 13:46:28 +0300 Subject: [PATCH] Started working on UI localization --- resources/w/ui/screen_settings.json | 6 +- resources/w/ui_en/hud_uni_int_dark_full.json | 241 ++++++++++++++++++ resources/w/ui_en/img/Hint_darklands001.png | 3 + .../w/ui_en/img/Hint_darklands002_attack.png | 3 + .../w/ui_en/img/Hint_darklands003_hp.png | 3 + resources/w/ui_en/img/Hint_m001.png | 3 + resources/w/ui_en/img/Location_dorm.png | 3 + resources/w/ui_en/img/Location_uni_ext.png | 3 + resources/w/ui_en/img/Location_uni_int.png | 3 + resources/w/ui_en/screen_language.json | 70 +++++ resources/w/ui_en/screen_main_menu.json | 124 +++++++++ src/Game.cpp | 10 + src/MenuManager.cpp | 168 +++++++----- src/MenuManager.h | 2 + 14 files changed, 570 insertions(+), 72 deletions(-) create mode 100644 resources/w/ui_en/hud_uni_int_dark_full.json create mode 100644 resources/w/ui_en/img/Hint_darklands001.png create mode 100644 resources/w/ui_en/img/Hint_darklands002_attack.png create mode 100644 resources/w/ui_en/img/Hint_darklands003_hp.png create mode 100644 resources/w/ui_en/img/Hint_m001.png create mode 100644 resources/w/ui_en/img/Location_dorm.png create mode 100644 resources/w/ui_en/img/Location_uni_ext.png create mode 100644 resources/w/ui_en/img/Location_uni_int.png create mode 100644 resources/w/ui_en/screen_language.json create mode 100644 resources/w/ui_en/screen_main_menu.json diff --git a/resources/w/ui/screen_settings.json b/resources/w/ui/screen_settings.json index 05dca2c..bc14771 100644 --- a/resources/w/ui/screen_settings.json +++ b/resources/w/ui/screen_settings.json @@ -85,17 +85,17 @@ "type": "TextButton", "name": "musicToggleButton", "width": 500, - "height": 60, + "height": 40, "text": "Music: ON", "fontSize": 32, "textCentered": true, "color": [0.2, 0.9, 0.2, 1.0] }, - { + { "type": "TextButton", "name": "soundToggleButton", "width": 500, - "height": 60, + "height": 40, "text": "Sound: ON", "fontSize": 32, "textCentered": true, diff --git a/resources/w/ui_en/hud_uni_int_dark_full.json b/resources/w/ui_en/hud_uni_int_dark_full.json new file mode 100644 index 0000000..c5f7b77 --- /dev/null +++ b/resources/w/ui_en/hud_uni_int_dark_full.json @@ -0,0 +1,241 @@ +{ + "root": { + "type": "FrameLayout", + "name": "hud_root", + "width": "match_parent", + "height": "match_parent", + "children": [ + { + "type": "Button", + "name": "settingsButton", + "horizontal_gravity": "right", + "vertical_gravity": "top", + "x": -35, + "y": -35, + "width": 200, + "height": 200, + "clickZoneWidth": 176, + "clickZoneHeight": 176, + "textures": { + "normal": "resources/w/ui/img/Settings001_State=Default001.png", + "hover": "resources/w/ui/img/Settings001_State=Selected001.png", + "pressed": "resources/w/ui/img/Settings001_State=Tap001.png" + } + }, + { + "type": "Button", + "name": "inventoryButton", + "horizontal_gravity": "right", + "vertical_gravity": "top", + "x": -18, + "y": 110, + "width": 165, + "height": 165, + "clickZoneWidth": 151, + "clickZoneHeight": 151, + "textures": { + "normal": "resources/w/ui/img/Inventory001_State=Default001.png", + "hover": "resources/w/ui/img/Inventory001_State=Selected001.png", + "pressed": "resources/w/ui/img/Inventory001_State=Tap001.png" + } + }, + { + "type": "Button", + "name": "journalButton", + "horizontal_gravity": "right", + "vertical_gravity": "top", + "x": -18, + "y": 220, + "width": 165, + "height": 165, + "clickZoneWidth": 89, + "clickZoneHeight": 89, + "textures": { + "normal": "resources/w/ui/img/Journal001_State=Default.png", + "hover": "resources/w/ui/img/Journal001_State=Selected.png", + "pressed": "resources/w/ui/img/Journal001_State=Tap.png" + } + }, + { + "type": "StaticImage", + "name": "location", + "width": 380, + "height": 64, + "y": 30, + "horizontal_gravity": "center", + "vertical_gravity": "bottom", + "texture": "resources/w/ui_en/img/Location_uni_int.png" + }, + { + "type": "StaticImage", + "name": "healthBarPanel", + "width": 389, + "height": 132.2, + "y": -5, + "x": -5, + "horizontal_gravity": "left", + "vertical_align": "top", + "texture": "resources/w/ui/img/HealthBarBase002.png" + }, + { + "type": "StaticImage", + "name": "healthBarBorder", + "width": 151.2, + "height": 22.8, + "y": 49.8, + "x": 100.6, + "horizontal_gravity": "left", + "vertical_align": "top", + "texture": "resources/w/ui/img/HealthBarBack001.png" + }, + { + "type": "Slider", + "name": "healthBarFill", + "width": 151.2, + "height": 22.8, + "y": 49.8, + "x": 100.6, + "horizontal_gravity": "left", + "vertical_gravity": "top", + "orientation": "horizontal", + "value": 1.0, + "fillMode": true, + "interactive": false, + "textures": { + "track": "resources/w/ui/img/HealthBarFill001.png" + } + }, + { + "type": "TextView", + "name": "healthValue", + "x": 255.0, + "y": 45.5, + "width": 100.0, + "height": 44.0, + "horizontal_gravity": "left", + "vertical_gravity": "top", + "text": "200/200", + "fontSize": 20, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": false, + "wrap": true, + "color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ] + }, + { + "type": "FrameLayout", + "vertical_align": "top", + "horizontal_align": "center", + "spacing": 0, + "width": "match_parent", + "height": 528, + "children": [ + { + "type": "StaticImage", + "name": "toast001", + "horizontal_gravity": "center", + "width": 504, + "height": 132, + "y": 0, + "visible" : false, + "texture": "resources/w/ui/img/toast/item_received001.png" + }, + { + "type": "StaticImage", + "name": "toast002", + "horizontal_gravity": "center", + "width": 504, + "height": 132, + "y": 104, + "visible" : false, + "texture": "resources/w/ui/img/toast/item_removed001.png" + }, + { + "type": "StaticImage", + "name": "toast003", + "horizontal_gravity": "center", + "width": 504, + "height": 132, + "y": 208, + "visible" : false, + "texture": "resources/w/ui/img/toast/quest_completed001.png" + }, + { + "type": "TextView", + "name": "toast001text", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "y": 62, + "x": 54, + "width": 400, + "height": 100, + "visible" : false, + "text": "", + "fontSize": 24, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": true, + "wrap": true, + "color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ] + }, + { + "type": "TextView", + "name": "toast002text", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "y": 166, + "x": 54, + "width": 400, + "height": 100, + "visible" : false, + "text": "", + "fontSize": 24, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": true, + "wrap": true, + "color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ] + }, + { + "type": "TextView", + "name": "toast003text", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "y": 270, + "x": 54, + "width": 400, + "height": 100, + "visible" : false, + "text": "", + "fontSize": 24, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": true, + "wrap": true, + "color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ] + } + ] + } + ] + } +} diff --git a/resources/w/ui_en/img/Hint_darklands001.png b/resources/w/ui_en/img/Hint_darklands001.png new file mode 100644 index 0000000..737e10d --- /dev/null +++ b/resources/w/ui_en/img/Hint_darklands001.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb1816bf8fef590dcb72afa90fe386d2b278d1532041608b335b5aea307efcb7 +size 278423 diff --git a/resources/w/ui_en/img/Hint_darklands002_attack.png b/resources/w/ui_en/img/Hint_darklands002_attack.png new file mode 100644 index 0000000..a541cf1 --- /dev/null +++ b/resources/w/ui_en/img/Hint_darklands002_attack.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:777b597949f3f473536c87d27613185b1f0b53f1667c6283685e0c09eb442abf +size 318379 diff --git a/resources/w/ui_en/img/Hint_darklands003_hp.png b/resources/w/ui_en/img/Hint_darklands003_hp.png new file mode 100644 index 0000000..7e42574 --- /dev/null +++ b/resources/w/ui_en/img/Hint_darklands003_hp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e82de1ff1df5b13fdce460b4db34c36be839aa3f6e434d6d2ac853644ef66f7 +size 357466 diff --git a/resources/w/ui_en/img/Hint_m001.png b/resources/w/ui_en/img/Hint_m001.png new file mode 100644 index 0000000..546f239 --- /dev/null +++ b/resources/w/ui_en/img/Hint_m001.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5cd2d7db0a2b27aeacc3272fc656a973ece5dab49cb91634479d2984c5c16bb +size 301554 diff --git a/resources/w/ui_en/img/Location_dorm.png b/resources/w/ui_en/img/Location_dorm.png new file mode 100644 index 0000000..dc32588 --- /dev/null +++ b/resources/w/ui_en/img/Location_dorm.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:83e8f9667899c4be245a4d2415dd74394d4361433c4d7e7b1385e4c33627bb9d +size 23793 diff --git a/resources/w/ui_en/img/Location_uni_ext.png b/resources/w/ui_en/img/Location_uni_ext.png new file mode 100644 index 0000000..90639c5 --- /dev/null +++ b/resources/w/ui_en/img/Location_uni_ext.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e30b357a82a345acb5954f59a624e22c9d8009500f03a373a28006227f6021d7 +size 25944 diff --git a/resources/w/ui_en/img/Location_uni_int.png b/resources/w/ui_en/img/Location_uni_int.png new file mode 100644 index 0000000..b0003e2 --- /dev/null +++ b/resources/w/ui_en/img/Location_uni_int.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:397d451a4080d88b24089e160ea821fa4b5576ce3f739e5dbdc141e3db0880ee +size 25434 diff --git a/resources/w/ui_en/screen_language.json b/resources/w/ui_en/screen_language.json new file mode 100644 index 0000000..fdd7494 --- /dev/null +++ b/resources/w/ui_en/screen_language.json @@ -0,0 +1,70 @@ +{ + "root": { + "type": "FrameLayout", + "width": "match_parent", + "height": "match_parent", + "children": [ + { + "type": "StaticImage", + "name": "languageBkg", + "width": "match_parent", + "height": "match_parent", + "texture": "resources/w/ui/img/main/bkg.png" + }, + { + "type": "LinearLayout", + "orientation": "vertical", + "horizontal_gravity": "center", + "vertical_gravity": "center", + "horizontal_align": "left", + "width": 500, + "height": 600, + "spacing": 20, + "children": [ + { + "type": "TextView", + "name": "languageTitleText", + "width": 500, + "height": 60, + "text": "Язык / Language", + "fontSize": 40, + "textCentered": true, + "color": [1.0, 1.0, 1.0, 1.0] + }, + { + "type": "TextButton", + "name": "languageRussianButton", + "width": 500, + "height": 80, + "text": "Русский", + "fontSize": 48, + "textCentered": true, + "color": [0.2, 0.9, 0.2, 1.0] + }, + { + "type": "TextButton", + "name": "languageEnglishButton", + "width": 500, + "height": 80, + "text": "English", + "fontSize": 48, + "textCentered": true, + "color": [0.2, 0.9, 0.2, 1.0] + } + ] + }, + { + "type": "TextButton", + "name": "languageBackButton", + "horizontal_gravity": "center", + "vertical_gravity": "bottom", + "y": 40, + "width": 200, + "height": 60, + "text": "Back", + "fontSize": 40, + "textCentered": true + } + ] + } +} diff --git a/resources/w/ui_en/screen_main_menu.json b/resources/w/ui_en/screen_main_menu.json new file mode 100644 index 0000000..efc663f --- /dev/null +++ b/resources/w/ui_en/screen_main_menu.json @@ -0,0 +1,124 @@ +{ + "root": { + "type": "FrameLayout", + "width": "match_parent", + "height": "match_parent", + "children": [ + { + "type": "StaticImage", + "name": "mainMenuBkg", + "width": 2186, + "height": 1536, + "texture": "resources/w/ui/img/main/MenuBkg001_v001.png" + }, + { + "type": "StaticImage", + "name": "mainMenuBkg2", + "horizontal_gravity": "center", + "vertical_gravity": "bottom", + "width": 720, + "height": 720, + "texture": "resources/w/ui/img/main/main002.png" + }, + { + "type": "StaticImage", + "name": "mainMenuUnderLetterBkg", + "horizontal_gravity": "center", + "width": 450, + "height": "match_parent", + "texture": "resources/w/ui/img/main/under_letters001.png" + }, + { + "type": "StaticImage", + "name": "mainMenuLogo", + "horizontal_gravity": "center", + "vertical_gravity": "center", + "width": 350, + "height": 175, + "y": 235, + "texture": "resources/w/ui/img/main/letters002.png" + }, + { + "type": "LinearLayout", + "orientation": "vertical", + "horizontal_align": "center", + "vertical_align": "center", + "spacing": 24, + "y": 120, + "width": "match_parent", + "height": "match_parent", + "children": [ + { + "type": "TextButton", + "name": "menuStartButton", + "width": 300, + "height": 60, + "text": "Start Game", + "fontSize": 48, + "textCentered": true + }, + { + "type": "TextButton", + "name": "menuLoadButton", + "width": 300, + "height": 60, + "text": "Load Game", + "fontSize": 48, + "textCentered": true + }, + { + "type": "TextButton", + "name": "menuSettingsButton", + "width": 300, + "height": 60, + "text": "Settings", + "fontSize": 48, + "textCentered": true + }, + { + "type": "TextButton", + "name": "menuLanguageButton", + "width": 300, + "height": 60, + "text": "Язык / Language", + "fontSize": 48, + "textCentered": true + }, + { + "type": "TextButton", + "name": "menuAboutButton", + "width": 300, + "height": 70, + "text": "About Us", + "fontSize": 48, + "textCentered": true + }, + { + "type": "TextButton", + "name": "menuExitButton", + "width": 300, + "height": 60, + "text": "Exit", + "fontSize": 48, + "textCentered": true + } + ] + }, + { + "type": "TextView", + "name": "mainMenuVersion", + "horizontal_gravity": "right", + "vertical_gravity": "bottom", + "x": 10, + "y": 10, + "width": 160, + "height": 36, + "text": "v. 0.7", + "fontSize": 24, + "textCentered": false, + "topAligned": true, + "paddingY": 4 + } + ] + } +} \ No newline at end of file diff --git a/src/Game.cpp b/src/Game.cpp index c3a8402..342ec4f 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -968,6 +968,16 @@ namespace ZL // Suppress all input while portrait overlay is shown //if (mobileIsPortrait) continue; + // Ignore pointer input until the initial loading screen has finished. + // Otherwise a click on the loading screen (e.g. at the spot where a + // main-menu button will later be) gets delivered to the menu UI as + // soon as it appears underneath, triggering that button unintentionally. + if (!loadingCompleted && + (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERUP || event.type == SDL_FINGERMOTION || + event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP)) { + continue; + } + #ifdef __ANDROID__ if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_AC_BACK) { Environment::exitGameLoop = true; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index bced095..2857eab 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -111,74 +111,89 @@ namespace ZL { localizedLocationName["location_dorm"][Language::English] = "Dormitory, 1st floor"; } + std::shared_ptr MenuManager::loadLocalizedUi(const std::string& basePath, const std::string& zipFile) { + static const std::string marker = "resources/w/ui/"; + if (basePath.rfind(marker, 0) == 0) { + const std::string localizedPath = "resources/w/ui_" + languageToCode(g_currentLanguage) + "/" + basePath.substr(marker.size()); + try { + return loadUiFromFile(localizedPath, renderer, zipFile); + } catch (const std::exception&) { + // Localized screen not available — fall back to the base path below. + } + } + return loadUiFromFile(basePath, renderer, zipFile); + } + + void MenuManager::loadUiRoots(const std::string& zipFile) { + hudRoot = loadLocalizedUi("resources/w/ui/hud_step0.json", zipFile); + hudStep1Root = loadLocalizedUi("resources/w/ui/hud_step1.json", zipFile); + hudStep2Root = loadLocalizedUi("resources/w/ui/hud_step2.json", zipFile); + hudStep3Root = loadLocalizedUi("resources/w/ui/hud_step3.json", zipFile); + hudStep4Root = loadLocalizedUi("resources/w/ui/hud_step4.json", zipFile); + hudStep5aRoot = loadLocalizedUi("resources/w/ui/hud_step5a.json", zipFile); + hudStep5bRoot = loadLocalizedUi("resources/w/ui/hud_step5b.json", zipFile); + hudStep5abRoot = loadLocalizedUi("resources/w/ui/hud_step5ab.json", zipFile); + hudUniExtRoot = loadLocalizedUi("resources/w/ui/hud_uni_ext.json", zipFile); + hudUniIntStep10Root = loadLocalizedUi("resources/w/ui/hud_uni_int_step10.json", zipFile); + hudUniIntStep11Root = loadLocalizedUi("resources/w/ui/hud_uni_int_step11.json", zipFile); + hudUniIntStep12Root = loadLocalizedUi("resources/w/ui/hud_uni_int_step12.json", zipFile); + hudUniIntStep13Root = loadLocalizedUi("resources/w/ui/hud_uni_int_step13.json", zipFile); + hudUniIntFullRoot = loadLocalizedUi("resources/w/ui/hud_uni_int_full.json", zipFile); + hudUniIntDarkFullRoot = loadLocalizedUi("resources/w/ui/hud_uni_int_dark_full.json", zipFile); + hudUniExtDarkRoot = loadLocalizedUi("resources/w/ui/hud_uni_ext_dark.json", zipFile); + + hudCutsceneRoot_ = loadLocalizedUi("resources/w/ui/hud_cutscene.json", zipFile); + hudTopHintRoot_ = loadLocalizedUi("resources/w/ui/hud_top_hint01.json", zipFile); + + phoneMainRoot = loadLocalizedUi("resources/w/ui/screen_phone.json", zipFile); + phoneMainHintARoot = loadLocalizedUi("resources/w/ui/screen_phone_hint001.json", zipFile); + phoneMainHintBRoot = loadLocalizedUi("resources/w/ui/screen_phone_hint002.json", zipFile); + phoneMainHintABRoot = loadLocalizedUi("resources/w/ui/screen_phone_hint001_002.json", zipFile); + + phoneBankRoot = loadLocalizedUi("resources/w/ui/screen_phone_bank.json", zipFile); + phoneVideoRoot = loadLocalizedUi("resources/w/ui/screen_phone_video.json", zipFile); + phoneMapDormRoot = loadLocalizedUi("resources/w/ui/screen_phone_map_dorm.json", zipFile); + phoneMapUniRoot = loadLocalizedUi("resources/w/ui/screen_phone_map_uni.json", zipFile); + + verticalPhoneMainRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone.json", zipFile); + verticalPhoneMainHintARoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_hint001.json", zipFile); + verticalPhoneMainHintBRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_hint002.json", zipFile); + verticalPhoneMainHintABRoot= loadLocalizedUi("resources/w/ui/portrait_screen_phone_hint001_002.json", zipFile); + verticalPhoneBankRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_bank.json", zipFile); + verticalPhoneVideoRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_video.json", zipFile); + verticalPhoneMapDormRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_map_dorm.json", zipFile); + verticalPhoneMapUniRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_map_uni.json", zipFile); + + phoneChatListRoot = loadLocalizedUi("resources/w/ui/screen_phone_chat_list.json", zipFile); + phoneChatListHintRoot = loadLocalizedUi("resources/w/ui/screen_phone_chat_list_hint001.json", zipFile); + verticalPhoneChatListRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_chat_list.json", zipFile); + verticalPhoneChatListHintRoot = loadLocalizedUi("resources/w/ui/portrait_screen_phone_chat_list_hint001.json", zipFile); + phoneChat1Root = loadLocalizedUi("resources/w/ui/screen_phone_chat1.json", zipFile); + phoneChat2Root = loadLocalizedUi("resources/w/ui/screen_phone_chat2.json", zipFile); + phoneChat3Root = loadLocalizedUi("resources/w/ui/screen_phone_chat3.json", zipFile); + verticalPhoneChat1Root = loadLocalizedUi("resources/w/ui/portrait_screen_phone_chat1.json", zipFile); + verticalPhoneChat2Root = loadLocalizedUi("resources/w/ui/portrait_screen_phone_chat2.json", zipFile); + verticalPhoneChat3Root = loadLocalizedUi("resources/w/ui/portrait_screen_phone_chat3.json", zipFile); + + modalMenuRoot = loadLocalizedUi("resources/w/ui/screen_modal_menu.json", zipFile); + newInventoryRoot = loadLocalizedUi("resources/w/ui/screen_inventory.json", zipFile); + portraitInventoryListRoot = loadLocalizedUi("resources/w/ui/portrait_screen_inventory.json", zipFile); + portraitInventoryItemRoot = loadLocalizedUi("resources/w/ui/portrait_screen_inventory_item.json", zipFile); + questJournalRoot = loadLocalizedUi("resources/w/ui/screen_journal.json", zipFile); + portraitQuestJournalListRoot = loadLocalizedUi("resources/w/ui/portrait_screen_journal.json", zipFile); + portraitQuestJournalItemRoot = loadLocalizedUi("resources/w/ui/portrait_screen_journal_item.json", zipFile); + mainMenuRoot = loadLocalizedUi("resources/w/ui/screen_main_menu.json", zipFile); + aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about.json", zipFile); + settingsScreenRoot = loadLocalizedUi("resources/w/ui/screen_settings.json", zipFile); + languageScreenRoot = loadLocalizedUi("resources/w/ui/screen_language.json", zipFile); + loadSavedGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_load.json", zipFile); + saveGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_save.json", zipFile); + } + void MenuManager::setup(Inventory& inv, const std::string& zipFile) { inventory = &inv; - - - hudRoot = loadUiFromFile("resources/w/ui/hud_step0.json", renderer, zipFile); - hudStep1Root = loadUiFromFile("resources/w/ui/hud_step1.json", renderer, zipFile); - hudStep2Root = loadUiFromFile("resources/w/ui/hud_step2.json", renderer, zipFile); - hudStep3Root = loadUiFromFile("resources/w/ui/hud_step3.json", renderer, zipFile); - hudStep4Root = loadUiFromFile("resources/w/ui/hud_step4.json", renderer, zipFile); - hudStep5aRoot = loadUiFromFile("resources/w/ui/hud_step5a.json", renderer, zipFile); - hudStep5bRoot = loadUiFromFile("resources/w/ui/hud_step5b.json", renderer, zipFile); - hudStep5abRoot = loadUiFromFile("resources/w/ui/hud_step5ab.json", renderer, zipFile); - hudUniExtRoot = loadUiFromFile("resources/w/ui/hud_uni_ext.json", renderer, zipFile); - hudUniIntStep10Root = loadUiFromFile("resources/w/ui/hud_uni_int_step10.json", renderer, zipFile); - hudUniIntStep11Root = loadUiFromFile("resources/w/ui/hud_uni_int_step11.json", renderer, zipFile); - hudUniIntStep12Root = loadUiFromFile("resources/w/ui/hud_uni_int_step12.json", renderer, zipFile); - hudUniIntStep13Root = loadUiFromFile("resources/w/ui/hud_uni_int_step13.json", renderer, zipFile); - hudUniIntFullRoot = loadUiFromFile("resources/w/ui/hud_uni_int_full.json", renderer, zipFile); - hudUniIntDarkFullRoot = loadUiFromFile("resources/w/ui/hud_uni_int_dark_full.json", renderer, zipFile); - hudUniExtDarkRoot = loadUiFromFile("resources/w/ui/hud_uni_ext_dark.json", renderer, zipFile); - - hudCutsceneRoot_ = loadUiFromFile("resources/w/ui/hud_cutscene.json", renderer, zipFile); - hudTopHintRoot_ = loadUiFromFile("resources/w/ui/hud_top_hint01.json", renderer, zipFile); - - phoneMainRoot = loadUiFromFile("resources/w/ui/screen_phone.json", renderer, zipFile); - phoneMainHintARoot = loadUiFromFile("resources/w/ui/screen_phone_hint001.json", renderer, zipFile); - phoneMainHintBRoot = loadUiFromFile("resources/w/ui/screen_phone_hint002.json", renderer, zipFile); - phoneMainHintABRoot = loadUiFromFile("resources/w/ui/screen_phone_hint001_002.json", renderer, zipFile); - - phoneBankRoot = loadUiFromFile("resources/w/ui/screen_phone_bank.json", renderer, zipFile); - phoneVideoRoot = loadUiFromFile("resources/w/ui/screen_phone_video.json", renderer, zipFile); - phoneMapDormRoot = loadUiFromFile("resources/w/ui/screen_phone_map_dorm.json", renderer, zipFile); - phoneMapUniRoot = loadUiFromFile("resources/w/ui/screen_phone_map_uni.json", renderer, zipFile); - - verticalPhoneMainRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone.json", renderer, zipFile); - verticalPhoneMainHintARoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_hint001.json", renderer, zipFile); - verticalPhoneMainHintBRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_hint002.json", renderer, zipFile); - verticalPhoneMainHintABRoot= loadUiFromFile("resources/w/ui/portrait_screen_phone_hint001_002.json", renderer, zipFile); - verticalPhoneBankRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_bank.json", renderer, zipFile); - verticalPhoneVideoRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_video.json", renderer, zipFile); - verticalPhoneMapDormRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_map_dorm.json", renderer, zipFile); - verticalPhoneMapUniRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_map_uni.json", renderer, zipFile); - - phoneChatListRoot = loadUiFromFile("resources/w/ui/screen_phone_chat_list.json", renderer, zipFile); - phoneChatListHintRoot = loadUiFromFile("resources/w/ui/screen_phone_chat_list_hint001.json", renderer, zipFile); - verticalPhoneChatListRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_chat_list.json", renderer, zipFile); - verticalPhoneChatListHintRoot = loadUiFromFile("resources/w/ui/portrait_screen_phone_chat_list_hint001.json", renderer, zipFile); - phoneChat1Root = loadUiFromFile("resources/w/ui/screen_phone_chat1.json", renderer, zipFile); - phoneChat2Root = loadUiFromFile("resources/w/ui/screen_phone_chat2.json", renderer, zipFile); - phoneChat3Root = loadUiFromFile("resources/w/ui/screen_phone_chat3.json", renderer, zipFile); - verticalPhoneChat1Root = loadUiFromFile("resources/w/ui/portrait_screen_phone_chat1.json", renderer, zipFile); - verticalPhoneChat2Root = loadUiFromFile("resources/w/ui/portrait_screen_phone_chat2.json", renderer, zipFile); - verticalPhoneChat3Root = loadUiFromFile("resources/w/ui/portrait_screen_phone_chat3.json", renderer, zipFile); - - modalMenuRoot = loadUiFromFile("resources/w/ui/screen_modal_menu.json", renderer, zipFile); - newInventoryRoot = loadUiFromFile("resources/w/ui/screen_inventory.json", renderer, zipFile); - portraitInventoryListRoot = loadUiFromFile("resources/w/ui/portrait_screen_inventory.json", renderer, zipFile); - portraitInventoryItemRoot = loadUiFromFile("resources/w/ui/portrait_screen_inventory_item.json", renderer, zipFile); - questJournalRoot = loadUiFromFile("resources/w/ui/screen_journal.json", renderer, zipFile); - portraitQuestJournalListRoot = loadUiFromFile("resources/w/ui/portrait_screen_journal.json", renderer, zipFile); - portraitQuestJournalItemRoot = loadUiFromFile("resources/w/ui/portrait_screen_journal_item.json", renderer, zipFile); - mainMenuRoot = loadUiFromFile("resources/w/ui/screen_main_menu.json", renderer, zipFile); - aboutScreenRoot = loadUiFromFile("resources/w/ui/screen_about.json", renderer, zipFile); - settingsScreenRoot = loadUiFromFile("resources/w/ui/screen_settings.json", renderer, zipFile); - languageScreenRoot = loadUiFromFile("resources/w/ui/screen_language.json", renderer, zipFile); - loadSavedGameScreenRoot = loadUiFromFile("resources/w/ui/screen_load.json", renderer, zipFile); - saveGameScreenRoot = loadUiFromFile("resources/w/ui/screen_save.json", renderer, zipFile); + loadUiRoots(zipFile); texObjectiveCompleted_ = renderer.textureManager.LoadFromPng("resources/w/ui/img/journal/quest_objective_completed.png", zipFile, true); texObjectiveBlank_ = renderer.textureManager.LoadFromPng("resources/w/ui/img/journal/quest_objective_blank.png", zipFile, true); @@ -407,10 +422,6 @@ namespace ZL { Environment::setFullscreen(!Environment::isFullscreen); refreshFullscreenToggle(); }); - - uiManager.setTextButtonCallback("languageButton", [this](const std::string&) { - showLanguageScreen(); - }); } void MenuManager::showLanguageScreen() { @@ -434,6 +445,25 @@ namespace ZL { void MenuManager::reloadLocalizedGameContent() { ItemRegistry::instance().loadFromJson("resources/config/items.json", CONST_ZIP_FILE); gameState_.questJournal.reloadDefinitionsPreservingState("resources/config/quests.json", CONST_ZIP_FILE); + + // Screens below the Language screen on the menu stack hold onto their old + // (pre-reload) UiNode instances, so simply reopening Language on top of + // them would leave Main Menu / Settings / the pause menu showing stale + // text once the player steps back. Instead, unwind the whole chain and + // replay it with freshly (re)loaded, localized roots. + const bool wasInMainMenu = (uiState_ == GameUiState::MainMenu); + + if (!wasInMainMenu) { + // Reached via the in-game pause menu (Modal -> Settings -> Language). + // Fully unwind back to the untouched gameplay HUD underneath — it + // isn't rebuilt here, only the pause/settings/language chain above it. + const int depth = uiManager.menuStackSize(); + for (int i = 0; i < depth; ++i) uiManager.popMenu(); + } + + loadUiRoots(CONST_ZIP_FILE); + + showMainMenu(); } void MenuManager::showLoadGameScreen() diff --git a/src/MenuManager.h b/src/MenuManager.h index 2d64af0..53f0664 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -122,6 +122,8 @@ namespace ZL { void applyHudForCurrentState(); void refreshQuestJournalUi(); void reloadLocalizedGameContent(); + std::shared_ptr loadLocalizedUi(const std::string& basePath, const std::string& zipFile); + void loadUiRoots(const std::string& zipFile); void selectQuestByIndex(int index); void refreshItemPickupHud(); void setupStep5Callbacks();