From bdad5fa10716e3ac9130ca7584a30d3baea17bae Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sat, 27 Jun 2026 13:07:16 +0300 Subject: [PATCH] Portrait mode for inventory screen --- .../w/ui/img/inv/PortraitInventoryBkg001.png | 3 + .../img/inv/PortraitInventoryItemBkg003.png | 3 + resources/w/ui/portrait_screen_inventory.json | 183 ++++++++++++++++++ .../w/ui/portrait_screen_inventory_item.json | 96 +++++++++ src/MenuManager.cpp | 121 ++++++++---- src/MenuManager.h | 5 + 6 files changed, 375 insertions(+), 36 deletions(-) create mode 100644 resources/w/ui/img/inv/PortraitInventoryBkg001.png create mode 100644 resources/w/ui/img/inv/PortraitInventoryItemBkg003.png create mode 100644 resources/w/ui/portrait_screen_inventory.json create mode 100644 resources/w/ui/portrait_screen_inventory_item.json diff --git a/resources/w/ui/img/inv/PortraitInventoryBkg001.png b/resources/w/ui/img/inv/PortraitInventoryBkg001.png new file mode 100644 index 0000000..369a980 --- /dev/null +++ b/resources/w/ui/img/inv/PortraitInventoryBkg001.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16b1a5a2f5295c0a2d7201da7d6ee2ea1b2667fe3156190d2ae6146649a2585d +size 226804 diff --git a/resources/w/ui/img/inv/PortraitInventoryItemBkg003.png b/resources/w/ui/img/inv/PortraitInventoryItemBkg003.png new file mode 100644 index 0000000..6e58ca9 --- /dev/null +++ b/resources/w/ui/img/inv/PortraitInventoryItemBkg003.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1a0b36c00457730f82f8a5212cba958500449d456f115d0bbb62a2dc64a6e5e +size 231883 diff --git a/resources/w/ui/portrait_screen_inventory.json b/resources/w/ui/portrait_screen_inventory.json new file mode 100644 index 0000000..d00211e --- /dev/null +++ b/resources/w/ui/portrait_screen_inventory.json @@ -0,0 +1,183 @@ +{ + "root": { + "type": "FrameLayout", + "name": "hud_root", + "width": "match_parent", + "height": "match_parent", + "vertical_align": "center", + "horizontal_align": "center", + "children": [ + { + "type": "StaticImage", + "name": "background", + "width": 640, + "height": 1200, + "y": 68, + "horizontal_gravity": "center", + "vertical_gravity": "top", + "texture": "resources/w/ui/img/inv/PortraitInventoryBkg001.png" + }, + { + "type": "StaticImage", + "name": "allItems", + "width": 220, + "height": 134, + "x": -210, + "y": 135, + "horizontal_gravity": "center", + "vertical_gravity": "top", + "texture": "resources/w/ui/img/inv/InventoryAllButton001.png" + }, + { + "type": "Button", + "name": "inventoryExitButton", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 120, + "height": 120, + "x": 267, + "y": 60, + "textures": { + "normal": "resources/w/ui/img/Close001_State=Default.png", + "hover": "resources/w/ui/img/Close001_State=Selected.png", + "pressed": "resources/w/ui/img/Close001_State=Tap.png" + } + }, + { + "type": "Button", + "name": "item1Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": -200, + "y": 250, + "textures": { + "normal": "resources/w/ui/img/inv/ItemSelPhone001.png", + "hover": "resources/w/ui/img/inv/ItemSelPhone001.png", + "pressed": "resources/w/ui/img/inv/ItemSelPhone001.png" + } + }, + { + "type": "Button", + "name": "item2Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": 0, + "y": 250, + "textures": { + "normal": "resources/w/ui/img/inv/ItemJournal001.png", + "hover": "resources/w/ui/img/inv/ItemJournal001.png", + "pressed": "resources/w/ui/img/inv/ItemJournal001.png" + } + }, + { + "type": "Button", + "name": "item3Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": 200, + "y": 250, + "textures": { + "normal": "resources/w/ui/img/inv/ItemKnife001.png", + "hover": "resources/w/ui/img/inv/ItemKnife001.png", + "pressed": "resources/w/ui/img/inv/ItemKnife001.png" + } + }, + { + "type": "Button", + "name": "item4Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": -200, + "y": 450, + "textures": { + "normal": "resources/w/ui/img/inv/ItemNote001.png", + "hover": "resources/w/ui/img/inv/ItemNote001.png", + "pressed": "resources/w/ui/img/inv/ItemNote001.png" + } + }, + { + "type": "Button", + "name": "item5Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": 0, + "y": 450, + "textures": { + "normal": "resources/w/ui/img/inv/ItemCoursework001.png", + "hover": "resources/w/ui/img/inv/ItemCoursework001.png", + "pressed": "resources/w/ui/img/inv/ItemCoursework001.png" + } + }, + { + "type": "Button", + "name": "item6Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": 200, + "y": 450, + "textures": { + "normal": "resources/w/ui/img/inv/ItemReportCard001.png", + "hover": "resources/w/ui/img/inv/ItemReportCard001.png", + "pressed": "resources/w/ui/img/inv/ItemReportCard001.png" + } + }, + { + "type": "Button", + "name": "item7Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": -200, + "y": 650, + "textures": { + "normal": "resources/w/ui/img/inv/ItemBook001.png", + "hover": "resources/w/ui/img/inv/ItemBook001.png", + "pressed": "resources/w/ui/img/inv/ItemBook001.png" + } + }, + { + "type": "Button", + "name": "item8Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": 0, + "y": 650, + "textures": { + "normal": "resources/w/ui/img/inv/ItemBook001.png", + "hover": "resources/w/ui/img/inv/ItemBook001.png", + "pressed": "resources/w/ui/img/inv/ItemBook001.png" + } + }, + { + "type": "Button", + "name": "item9Button", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 274, + "height": 274, + "x": -200, + "y": 650, + "textures": { + "normal": "resources/w/ui/img/inv/ItemBook001.png", + "hover": "resources/w/ui/img/inv/ItemBook001.png", + "pressed": "resources/w/ui/img/inv/ItemBook001.png" + } + } + ] + } +} \ No newline at end of file diff --git a/resources/w/ui/portrait_screen_inventory_item.json b/resources/w/ui/portrait_screen_inventory_item.json new file mode 100644 index 0000000..0919917 --- /dev/null +++ b/resources/w/ui/portrait_screen_inventory_item.json @@ -0,0 +1,96 @@ +{ + "root": { + "type": "FrameLayout", + "name": "hud_root", + "width": "match_parent", + "height": "match_parent", + "vertical_align": "center", + "horizontal_align": "center", + "children": [ + { + "type": "StaticImage", + "name": "background", + "width": 640, + "height": 1200, + "y": 68, + "horizontal_gravity": "center", + "vertical_gravity": "top", + "texture": "resources/w/ui/img/inv/PortraitInventoryItemBkg003.png" + }, + { + "type": "Button", + "name": "inventoryExitButton", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "width": 120, + "height": 120, + "x": 267, + "y": 60, + "textures": { + "normal": "resources/w/ui/img/Close001_State=Default.png", + "hover": "resources/w/ui/img/Close001_State=Selected.png", + "pressed": "resources/w/ui/img/Close001_State=Tap.png" + } + }, + { + "type": "StaticImage", + "name": "selectedItemPic", + "width": 274, + "height": 274, + "x": -200, + "y": 190, + "horizontal_gravity": "center", + "vertical_gravity": "top", + "texture": "resources/w/ui/img/inv/ItemSelReportCard001.png" + }, + { + "type": "TextView", + "name": "selectedText", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "x": 10, + "y": 140, + "width": 600, + "height": 137, + "text": "Серебряный нож.", + "fontSize": 60, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": true, + "wrap": true, + "paddingX": 0.0, + "paddingY": 0.0, + "color": [ + 0.318, + 0.635, + 1.0, + 1.0 + ] + }, + { + "type": "TextView", + "name": "selectedDescription", + "horizontal_gravity": "center", + "vertical_gravity": "top", + "x": 4.0, + "y": 520.0, + "width": 580.0, + "height": 400.0, + "text": "А все бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут бегут а мы идем.", + "fontSize": 48, + "fontPath": "resources/fonts/DroidSans.ttf", + "textCentered": false, + "topAligned": true, + "wrap": true, + "paddingX": 0.0, + "paddingY": 0.0, + "color": [ + 1.0, + 1.0, + 1.0, + 1.0 + ] + } + ] + } +} \ No newline at end of file diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 943f79a..a52138f 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -159,6 +159,8 @@ namespace ZL { 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); @@ -444,54 +446,49 @@ namespace ZL { void MenuManager::openInventory() { uiState_ = GameUiState::Inventory; - uiManager.pushMenuFromSavedRoot(newInventoryRoot); + inventoryMenuStackDepth_ = 1; + + const bool portrait = isPortraitMode(); + uiManager.pushMenuFromSavedRoot(portrait ? portraitInventoryListRoot : newInventoryRoot); + uiManager.setButtonCallback("inventoryExitButton", [this](const std::string&) { closeInventory(); - }); + }); const auto& items = inventory->getItems(); - std::string itemText; - if (items.empty()) { - itemText = "Inventory (Empty)"; - } - else { - itemText = "Inventory (" + std::to_string(items.size()) + " items)\n\n"; - for (size_t i = 0; i < items.size(); ++i) { - itemText += std::to_string(i + 1) + ". " + items[i].name + "\n"; - const int maxSlots = 9; - - for (int i = 0; i < maxSlots; ++i) { - const std::string btnName = "item" + std::to_string(i + 1) + "Button"; - if (i < static_cast(items.size())) { - uiManager.setNodeVisible(btnName, true); - - auto btn = uiManager.findButton(btnName); - if (btn) { - auto tex = renderer.textureManager.LoadFromPng(items[i].icon, CONST_ZIP_FILE, true); - btn->texNormal = btn->texHover = btn->texPressed = tex; - } - - uiManager.setButtonCallback(btnName, [this, i](const std::string&) { - selectInventoryItem(i); - }); - } - else { - uiManager.setNodeVisible(btnName, false); - } - } - - inventorySelectedIndex_ = -1; - if (!items.empty()) { - selectInventoryItem(0); + const int maxSlots = 9; + for (int i = 0; i < maxSlots; ++i) { + const std::string btnName = "item" + std::to_string(i + 1) + "Button"; + if (i < static_cast(items.size())) { + uiManager.setNodeVisible(btnName, true); + auto btn = uiManager.findButton(btnName); + if (btn) { + auto tex = renderer.textureManager.LoadFromPng(items[i].icon, CONST_ZIP_FILE, true); + btn->texNormal = btn->texHover = btn->texPressed = tex; } + uiManager.setButtonCallback(btnName, [this, i](const std::string&) { + selectInventoryItem(i); + }); + } else { + uiManager.setNodeVisible(btnName, false); } } + + inventorySelectedIndex_ = -1; + if (!portrait && !items.empty()) { + selectInventoryItem(0); + } } void MenuManager::selectInventoryItem(int index) { const auto& items = inventory->getItems(); if (index < 0 || index >= static_cast(items.size())) return; + if (isPortraitMode() && inventoryMenuStackDepth_ == 1) { + openPortraitInventoryItem(index); + return; + } + // Revert previously selected button to its regular icon if (inventorySelectedIndex_ >= 0 && inventorySelectedIndex_ < static_cast(items.size())) { const std::string prevBtnName = "item" + std::to_string(inventorySelectedIndex_ + 1) + "Button"; @@ -528,7 +525,8 @@ namespace ZL { void MenuManager::closeInventory() { uiState_ = GameUiState::Gameplay; - uiManager.popMenu(); + for (int i = 0; i < inventoryMenuStackDepth_; ++i) uiManager.popMenu(); + inventoryMenuStackDepth_ = 0; uiManager.updateAllLayouts(); } @@ -1290,6 +1288,34 @@ namespace ZL { refreshQuestJournalUi(); } + void MenuManager::openPortraitInventoryItem(int index) { + const auto& items = inventory->getItems(); + inventorySelectedIndex_ = index; + inventoryMenuStackDepth_ = 2; + uiManager.pushMenuFromSavedRoot(portraitInventoryItemRoot); + + uiManager.setButtonCallback("inventoryExitButton", [this](const std::string&) { + closePortraitInventoryItem(); + }); + + const auto& item = items[index]; + + auto img = uiManager.findStaticImage("selectedItemPic"); + if (img) { + const std::string& path = item.selectedIcon.empty() ? item.icon : item.selectedIcon; + img->texture = renderer.textureManager.LoadFromPng(path, CONST_ZIP_FILE, true); + } + uiManager.setText("selectedText", item.name); + uiManager.setText("selectedDescription", item.description); + uiManager.updateAllLayouts(); + } + + void MenuManager::closePortraitInventoryItem() { + inventoryMenuStackDepth_ = 1; + uiManager.popMenu(); + uiManager.updateAllLayouts(); + } + void MenuManager::openPortraitQuestJournalItem(int index) { selectedQuestIndex = index; journalMenuStackDepth_ = 2; @@ -1770,6 +1796,29 @@ namespace ZL { } void MenuManager::onOrientationChanged() { + if (uiState_ == GameUiState::Inventory) { + const int savedIndex = inventorySelectedIndex_; + const bool wasOnItemDetail = (inventoryMenuStackDepth_ == 2); + + for (int i = 0; i < inventoryMenuStackDepth_; ++i) uiManager.popMenu(); + inventoryMenuStackDepth_ = 0; + uiState_ = GameUiState::Gameplay; + inventorySelectedIndex_ = -1; + + openInventory(); + + const int itemCount = static_cast(inventory->getItems().size()); + if (isPortraitMode() && wasOnItemDetail && + savedIndex >= 0 && savedIndex < itemCount) { + selectInventoryItem(savedIndex); + } else if (!isPortraitMode() && savedIndex > 0 && savedIndex < itemCount) { + selectInventoryItem(savedIndex); + } + + uiManager.updateAllLayouts(); + return; + } + if (uiState_ == GameUiState::QuestJournal) { const int savedQuestIndex = selectedQuestIndex; const bool wasOnItemDetail = (journalMenuStackDepth_ == 2); diff --git a/src/MenuManager.h b/src/MenuManager.h index a988ca3..272fca9 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -138,6 +138,8 @@ namespace ZL { void rebuildChatBubblesFromHistory(int chatIndex, bool isPortrait); void showModalMenuScreen(); + void openPortraitInventoryItem(int index); + void closePortraitInventoryItem(); void openPortraitQuestJournalItem(int index); void closePortraitJournalItem(); @@ -170,6 +172,7 @@ namespace ZL { Inventory* inventory = nullptr; int inventorySelectedIndex_ = -1; + int inventoryMenuStackDepth_ = 0; int selectedQuestIndex = -1; int journalMenuStackDepth_ = 0; std::vector visibleQuestIds; @@ -235,6 +238,8 @@ namespace ZL { std::shared_ptr newInventoryRoot; + std::shared_ptr portraitInventoryListRoot; + std::shared_ptr portraitInventoryItemRoot; std::shared_ptr questJournalRoot; std::shared_ptr portraitQuestJournalListRoot; std::shared_ptr portraitQuestJournalItemRoot;