From b3fa7a53a29a1001935514a38f140af2b816771a Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 9 Aug 2017 18:47:10 +0300 Subject: Allow for each item replace equip/use menu item to custom menu. Separate menus supproted for inventory, storage, cart. --- src/CMakeLists.txt | 1 + src/Makefile.am | 1 + src/gui/popups/popupmenu.cpp | 68 +++++++++++++++++++++++++--- src/gui/popups/popupmenu.h | 9 +++- src/resources/db/itemdb.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++ src/resources/iteminfo.cpp | 3 ++ src/resources/iteminfo.h | 18 ++++++++ src/resources/itemmenuitem.h | 49 ++++++++++++++++++++ 8 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 src/resources/itemmenuitem.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1c680d668..8eddf51e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -694,6 +694,7 @@ SET(SRCS resources/db/languagedb.h resources/iteminfo.h resources/iteminfo.cpp + resources/itemmenuitem.h enums/resources/cursor.h enums/resources/frametype.h enums/resources/imageposition.h diff --git a/src/Makefile.am b/src/Makefile.am index 42342a576..88478e3c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1449,6 +1449,7 @@ SRC = ${BASE_SRC} \ resources/db/weaponsdb.h \ resources/iteminfo.h \ resources/iteminfo.cpp \ + resources/itemmenuitem.h \ enums/resources/cursor.h \ enums/resources/frametype.h \ enums/resources/imageposition.h \ diff --git a/src/gui/popups/popupmenu.cpp b/src/gui/popups/popupmenu.cpp index ba71e8d04..1b9a50c5b 100644 --- a/src/gui/popups/popupmenu.cpp +++ b/src/gui/popups/popupmenu.cpp @@ -1660,7 +1660,8 @@ void PopupMenu::showPopup(Window *const parent, _("Move to craft...")); } } - addUseDrop(item, isProtected); + addItemMenu(item, InventoryType::Inventory); + addDrop(item, isProtected); break; case InventoryType::Storage: @@ -1688,12 +1689,16 @@ void PopupMenu::showPopup(Window *const parent, // TRANSLATORS: popup menu item // TRANSLATORS: get all item amount from storage _("Retrieve all")); + mBrowserBox->addSeparator("##3---"); } + addItemMenu(item, InventoryType::Storage); + break; + case InventoryType::Cart: + addItemMenu(item, InventoryType::Cart); break; case InventoryType::Trade: case InventoryType::Npc: - case InventoryType::Cart: case InventoryType::Vending: case InventoryType::Mail: case InventoryType::Craft: @@ -1794,7 +1799,8 @@ void PopupMenu::showItemPopup(const int x, const int y, if (item != nullptr) { const bool isProtected = PlayerInfo::isItemProtected(mItemId); - addUseDrop(item, isProtected); + addUse(item); + addDrop(item, isProtected); if (InventoryWindow::isStorageActive()) { // TRANSLATORS: popup menu item @@ -1842,7 +1848,8 @@ void PopupMenu::showDropPopup(const int x, for (int f = 0; f < maxCards; f ++) mItemCards[f] = item->getCard(f); const bool isProtected = PlayerInfo::isItemProtected(mItemId); - addUseDrop(item, isProtected); + addUse(item); + addDrop(item, isProtected); if (InventoryWindow::isStorageActive()) { // TRANSLATORS: popup menu item @@ -2767,7 +2774,7 @@ void PopupMenu::addProtection() } } -void PopupMenu::addUseDrop(const Item *const item, const bool isProtected) +void PopupMenu::addUse(const Item *const item) { const ItemInfo &info = item->getInfo(); const std::string &str = (item->isEquipment() == Equipm_true @@ -2784,7 +2791,58 @@ void PopupMenu::addUseDrop(const Item *const item, const bool isProtected) // TRANSLATORS: popup menu item mBrowserBox->addRow("/useinv 'INVINDEX'", str.c_str()); } +} + +void PopupMenu::addItemMenu(const Item *const item, + const InventoryTypeT type) +{ + const ItemInfo &info = item->getInfo(); + const STD_VECTOR *menu = nullptr; + switch (type) + { + case InventoryType::Inventory: + menu = &info.getInventoryMenuConst(); + break; + case InventoryType::Storage: + menu = &info.getStorageMenuConst(); + break; + case InventoryType::Cart: + menu = &info.getCartMenuConst(); + break; + case InventoryType::Trade: + case InventoryType::Npc: + case InventoryType::Vending: + case InventoryType::Mail: + case InventoryType::Craft: + case InventoryType::TypeEnd: + default: + return; + } + const bool firstMode = (item->isEquipment() == Equipm_true ? + (item->isEquipped() != Equipped_true) : + (item->getQuantity() == 1)); + + FOR_EACHP (STD_VECTOR::const_iterator, it, menu) + { + const ItemMenuItem &menuItem = *it; + const std::string &name = firstMode ? + menuItem.name1 : menuItem.name2; + const std::string &command = firstMode ? + menuItem.command1 : menuItem.command2; + if (command.empty() || + name.empty()) + { + continue; + } + mBrowserBox->addRow("/" + command, name.c_str()); + } + mBrowserBox->addSeparator("##3---"); +} + +void PopupMenu::addDrop(const Item *const item, + const bool isProtected) +{ if (!isProtected) { mBrowserBox->addSeparator("##3---"); diff --git a/src/gui/popups/popupmenu.h b/src/gui/popups/popupmenu.h index 6d0c141f5..5b554e197 100644 --- a/src/gui/popups/popupmenu.h +++ b/src/gui/popups/popupmenu.h @@ -234,8 +234,13 @@ class PopupMenu final : public Popup, public LinkHandler void addProtection(); - void addUseDrop(const Item *const item, - const bool isProtected) A_NONNULL(2); + void addUse(const Item *const item) A_NONNULL(2); + + void addItemMenu(const Item *const item, + const InventoryTypeT type) A_NONNULL(2); + + void addDrop(const Item *const item, + const bool isProtected) A_NONNULL(2); void addGmCommands(); diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp index 6a7ed29eb..93c0e845a 100644 --- a/src/resources/db/itemdb.cpp +++ b/src/resources/db/itemdb.cpp @@ -236,6 +236,56 @@ void ItemDB::load() } } +static void loadMenu(XmlNodePtrConst parentNode, + STD_VECTOR &menu) +{ + for_each_xml_child_node(node, parentNode) + { + if (xmlNameEqual(node, "menu")) + { + const std::string name1 = XML::langProperty(node, + "name1", ""); + const std::string name2 = XML::langProperty(node, + "name2", ""); + const std::string command1 = XML::getProperty(node, + "command1", ""); + const std::string command2 = XML::getProperty(node, + "command2", command1); + menu.push_back(ItemMenuItem(name1, + name2, + command1, + command2)); + } + } +} + +static bool getIsEquipment(const ItemDbType type) +{ + switch (type) + { + case ItemDbType::EQUIPMENT_ONE_HAND_WEAPON: + case ItemDbType::EQUIPMENT_TWO_HANDS_WEAPON: + case ItemDbType::EQUIPMENT_TORSO: + case ItemDbType::EQUIPMENT_ARMS: + case ItemDbType::EQUIPMENT_HEAD: + case ItemDbType::EQUIPMENT_LEGS: + case ItemDbType::EQUIPMENT_SHIELD: + case ItemDbType::EQUIPMENT_RING: + case ItemDbType::EQUIPMENT_NECKLACE: + case ItemDbType::EQUIPMENT_FEET: + case ItemDbType::EQUIPMENT_AMMO: + case ItemDbType::EQUIPMENT_CHARM: + return true; + case ItemDbType::UNUSABLE: + case ItemDbType::USABLE: + case ItemDbType::CARD: + case ItemDbType::SPRITE_RACE: + case ItemDbType::SPRITE_HAIR: + default: + return false; + } +} + void ItemDB::loadXmlFile(const std::string &fileName, int &tagNum, const SkipError skipError) @@ -582,6 +632,18 @@ void ItemDB::loadXmlFile(const std::string &fileName, { loadOrderSprite(itemInfo, itemChild, false); } + else if (xmlNameEqual(itemChild, "inventory")) + { + loadMenu(itemChild, itemInfo->getInventoryMenu()); + } + else if (xmlNameEqual(itemChild, "storage")) + { + loadMenu(itemChild, itemInfo->getStorageMenu()); + } + else if (xmlNameEqual(itemChild, "cart")) + { + loadMenu(itemChild, itemInfo->getCartMenu()); + } } /* @@ -643,6 +705,47 @@ void ItemDB::loadXmlFile(const std::string &fileName, } } + STD_VECTOR &inventoryMenu = itemInfo->getInventoryMenu(); + + if (inventoryMenu.empty()) + { + std::string name1 = itemInfo->getUseButton(); + std::string name2 = itemInfo->getUseButton2(); + const bool isEquipment = getIsEquipment(itemInfo->getType()); + + if (isEquipment) + { + if (name1.empty()) + { + // TRANSLATORS: popup menu item + name1 = _("Equip"); + } + if (name2.empty()) + { + // TRANSLATORS: popup menu item + name2 = _("Unequip"); + } + } + else + { + if (name1.empty()) + { + // TRANSLATORS: popup menu item + name1 = _("Use"); + } + if (name2.empty()) + { + // TRANSLATORS: popup menu item + name2 = _("Use"); + } + } + inventoryMenu.push_back(ItemMenuItem( + name1, + name2, + "useinv 'INVINDEX'", + "useinv 'INVINDEX'")); + } + #define CHECK_PARAM(param) \ if (param.empty()) \ { \ diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 26cd2dc20..118ce5d71 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -63,6 +63,9 @@ ItemInfo::ItemInfo() : mTags(), mColorsList(nullptr), mIconColorsList(nullptr), + mInventoryMenu(), + mStorageMenu(), + mCartMenu(), mColorsListName(), mIconColorsListName(), mCardColor(ItemColor_zero), diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 92474ff7e..414fa45b8 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -31,6 +31,7 @@ #include "resources/cursors.h" #include "resources/itemcolordata.h" +#include "resources/itemmenuitem.h" #include "resources/missileinfo.h" #include "resources/soundinfo.h" @@ -313,6 +314,20 @@ class ItemInfo final std::string getIconColorName(const ItemColor idx) const; std::string getIconColor(const ItemColor idx) const; + STD_VECTOR &getInventoryMenu() + { return mInventoryMenu; } + STD_VECTOR &getStorageMenu() + { return mStorageMenu; } + STD_VECTOR &getCartMenu() + { return mCartMenu; } + + const STD_VECTOR &getInventoryMenuConst() const A_CONST + { return mInventoryMenu; } + const STD_VECTOR &getStorageMenuConst() const A_CONST + { return mStorageMenu; } + const STD_VECTOR &getCartMenuConst() const A_CONST + { return mCartMenu; } + int mDrawBefore[10]; int mDrawAfter[10]; int mDrawPriority[10]; @@ -363,6 +378,9 @@ class ItemInfo final std::map mTags; const std::map *mColorsList; const std::map *mIconColorsList; + STD_VECTOR mInventoryMenu; + STD_VECTOR mStorageMenu; + STD_VECTOR mCartMenu; std::string mColorsListName; std::string mIconColorsListName; ItemColor mCardColor; diff --git a/src/resources/itemmenuitem.h b/src/resources/itemmenuitem.h new file mode 100644 index 000000000..0d7dd2950 --- /dev/null +++ b/src/resources/itemmenuitem.h @@ -0,0 +1,49 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012-2017 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef RESOURCES_ITEMMENUITEM_H +#define RESOURCES_ITEMMENUITEM_H + +#include + +#include "localconsts.h" + +struct ItemMenuItem final +{ + ItemMenuItem(const std::string &name01, + const std::string &name02, + const std::string &command01, + const std::string &command02) : + name1(name01), + name2(name02), + command1(command01), + command2(command02) + { + } + + A_DEFAULT_COPY(ItemMenuItem) + + std::string name1; + std::string name2; + std::string command1; + std::string command2; +}; + +#endif // RESOURCES_ITEMMENUITEM_H -- cgit v1.2.3-60-g2f50