diff --git a/client/widgets/CTradeBase.cpp b/client/widgets/CTradeBase.cpp index 5bf473d44..99b225073 100644 --- a/client/widgets/CTradeBase.cpp +++ b/client/widgets/CTradeBase.cpp @@ -258,8 +258,32 @@ void CTradeableItem::setArtInstance(const CArtifactInstance * art) setID(-1); } -SResourcesPanel::SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updatePanelFunctor updateSubtitles) - : updateSubtitles(updateSubtitles) +void STradePanel::updateSlots() +{ + if(updateSlotsCallback) + updateSlotsCallback(); +} + +void STradePanel::deselect() +{ + for(auto & slot : slots) + slot->selection->selectSlot(false); +} + +void STradePanel::clearSubtitles() +{ + for(auto & slot : slots) + slot->subtitle.clear(); +} + +void STradePanel::updateOffer(int slotIdx, int cost, int qty) +{ + slots[slotIdx]->subtitle = std::to_string(qty); + if(cost != 1) + slots[slotIdx]->subtitle += "/" + std::to_string(cost); +} + +SResourcesPanel::SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updateSlotsFunctor updateSubtitles) { assert(resourcesForTrade.size() == slotsPos.size()); OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE); @@ -271,18 +295,26 @@ SResourcesPanel::SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPresse slots.back()->pos.w = 69; slots.back()->pos.h = 66; slots.back()->selection = std::make_unique(Rect(slotsPos[res.num], slots.back()->pos.dimensions())); } + updateSlotsCallback = updateSubtitles; } -void SResourcesPanel::updateSlots() +SArtifactsPanel::SArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updateSlotsFunctor updateSubtitles, + std::vector & arts) { - if(updateSubtitles) - updateSubtitles(); -} + assert(artifactsForTrade == slotsPos.size()); + assert(artifactsForTrade == arts.size()); + OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE); -void SResourcesPanel::deselect() -{ + slots.resize(artifactsForTrade); + int slotNum = 0; for(auto & slot : slots) - slot->selection->selectSlot(false); + { + slot = std::make_shared(slotsPos[slotNum], EType::ARTIFACT_TYPE, arts[slotNum].getNum(), false, slotNum); + slot->clickPressedCallback = clickPressedCallback; + slot->pos.w = slot->pos.h = 44; + slot->selection = std::make_unique(Rect(slotsPos[slotNum++], slot->pos.dimensions())); + } + updateSlotsCallback = updateSubtitles; } CTradeBase::CTradeBase(const IMarket * market, const CGHeroInstance * hero) diff --git a/client/widgets/CTradeBase.h b/client/widgets/CTradeBase.h index 91237732e..4a7374126 100644 --- a/client/widgets/CTradeBase.h +++ b/client/widgets/CTradeBase.h @@ -11,7 +11,8 @@ #include "Images.h" -#include "../../lib/FunctionList.h" +#include "../lib/FunctionList.h" +#include "../lib/networkPacks/TradeItem.h" VCMI_LIB_NAMESPACE_BEGIN @@ -64,10 +65,22 @@ public: CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial); }; -struct SResourcesPanel : public CIntObject +struct STradePanel : public CIntObject { - using updatePanelFunctor = std::function; + using updateSlotsFunctor = std::function; + std::vector> slots; + std::function updateSlotsCallback; + std::shared_ptr selected; + + virtual void updateSlots(); + virtual void deselect(); + virtual void clearSubtitles(); + void updateOffer(int slotIdx, int, int); +}; + +struct SResourcesPanel : public STradePanel +{ const std::vector resourcesForTrade = { GameResID::WOOD, GameResID::MERCURY, GameResID::ORE, @@ -80,12 +93,22 @@ struct SResourcesPanel : public CIntObject Point(0, 79), Point(83, 79), Point(166, 79), Point(83, 158) }; - std::vector> slots; - std::function updateSubtitles; - SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updatePanelFunctor updateSubtitles); - void updateSlots(); - void deselect(); + SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updateSlotsFunctor updateSubtitles); +}; + +struct SArtifactsPanel : public STradePanel +{ + const std::vector slotsPos = + { + Point(0, 0), Point(83, 0), Point(166, 0), + Point(0, 79), Point(83, 79), Point(166, 79), + Point(83, 158) + }; + const size_t artifactsForTrade = 7; + + SArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, updateSlotsFunctor updateSubtitles, + std::vector & arts); }; class CTradeBase @@ -96,8 +119,7 @@ public: //all indexes: 1 = left, 0 = right std::array>, 2> items; - std::shared_ptr resoursesPanelPlayer; - std::shared_ptr resoursesPanelMarket; + std::vector> tradePanels; //highlighted items (nullptr if no highlight) std::shared_ptr hLeft; diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index d6f3d4ec9..4b927b495 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -86,7 +86,7 @@ void CTradeWindow::initItems(bool Left) { if(Left && itemsType[1] == RESOURCE) { - resoursesPanelPlayer = std::make_shared( + tradePanels.emplace_back(std::make_shared( [this](std::shared_ptr marketSlot) -> void { if(hLeft != marketSlot) @@ -97,19 +97,19 @@ void CTradeWindow::initItems(bool Left) hLeft->selection->selectSlot(true); selectionChanged(true); } - }, + }, [this]() -> void { - for(auto & slot : resoursesPanelPlayer->slots) + for(auto & slot : tradePanels[1]->slots) slot->subtitle = std::to_string(LOCPLINT->cb->getResourceAmount(static_cast(slot->serial))); - }); - resoursesPanelPlayer->moveBy(Point(39, 182)); - resoursesPanelPlayer->updateSlots(); + })); + tradePanels.back()->moveBy(Point(39, 182)); + tradePanels.back()->updateSlots(); return; } if(!Left && itemsType[0] == RESOURCE) { - resoursesPanelMarket = std::make_shared( + tradePanels.emplace_back(std::make_shared( [this](std::shared_ptr marketSlot) -> void { if(hRight != marketSlot) @@ -124,31 +124,53 @@ void CTradeWindow::initItems(bool Left) }, [this]() -> void { - for(auto & slot : resoursesPanelMarket->slots) - { - if(hLeft) //artifact, creature + if(hLeft) + for(auto & slot : tradePanels[0]->slots) { int h1, h2; //hlp variables for getting offer - market->getOffer(hLeft->id, slot->id, h1, h2, mode); - if(slot->id != hLeft->id || mode != EMarketMode::RESOURCE_RESOURCE) //don't allow exchanging same resources - { - std::ostringstream oss; - oss << h2; - if(h1 != 1) - oss << "/" << h1; - slot->subtitle = oss.str(); - } + market->getOffer(hLeft->id, slot->id, h1, h2, EMarketMode::RESOURCE_RESOURCE); + + if(slot->id != hLeft->id) + tradePanels[0]->updateOffer(slot->serial, h1, h2); else slot->subtitle = CGI->generaltexth->allTexts[164]; // n/a } - else - slot->subtitle = ""; - } - }); - resoursesPanelMarket->moveBy(Point(327, 182)); + else + tradePanels[0]->clearSubtitles(); + })); + tradePanels.back()->moveBy(Point(327, 182)); + return; + } + if(!Left && itemsType[0] == ARTIFACT_TYPE) + { + tradePanels.emplace_back(std::make_shared( + [this](std::shared_ptr marketSlot) -> void + { + if(hRight != marketSlot) + { + if(hRight) + hRight->selection->selectSlot(false); + hRight = marketSlot; + hRight->selection->selectSlot(true); + selectionChanged(false); + initSubs(false); + } + }, + [this]() -> void + { + if(hLeft) + for(auto & slot : tradePanels[0]->slots) + { + int h1, h2; //hlp variables for getting offer + market->getOffer(hLeft->id, slot->id, h1, h2, EMarketMode::RESOURCE_ARTIFACT); + tradePanels[0]->updateOffer(slot->serial, h1, h2); + } + else + tradePanels[0]->clearSubtitles(); + }, market->availableItemsIds(mode))); + tradePanels.back()->moveBy(Point(340, 182)); return; } - std::vector *ids = getItemsIds(Left); std::vector pos; @@ -229,12 +251,6 @@ std::vector *CTradeWindow::getItemsIds(bool Left) if(PlayerColor(i) != LOCPLINT->playerID && LOCPLINT->cb->getPlayerStatus(PlayerColor(i)) == EPlayerStatus::INGAME) ids->push_back(i); break; - - case ARTIFACT_TYPE: - ids = new std::vector; - for (auto const & item : market->availableItemsIds(mode)) - ids->push_back(item.getNum()); - break; } } @@ -269,14 +285,6 @@ void CTradeWindow::getPositionsFor(std::vector &poss, bool Left, EType typ dy = 98; assert(Left); break; - case ARTIFACT_TYPE://45,123 - x = 340 - 289; - y = 180; - w = 44; - h = 44; - dx = 83; - dy = 79; - break; } int leftToRightOffset = 289; @@ -302,12 +310,12 @@ void CTradeWindow::getPositionsFor(std::vector &poss, bool Left, EType typ void CTradeWindow::initSubs(bool Left) { - if(itemsType[Left] == RESOURCE) + if(itemsType[Left] == RESOURCE || itemsType[Left] == ARTIFACT_TYPE) { if(Left) - resoursesPanelPlayer->updateSlots(); + tradePanels[1]->updateSlots(); else - resoursesPanelMarket->updateSlots(); + tradePanels[0]->updateSlots(); return; } @@ -590,10 +598,8 @@ void CMarketplaceWindow::makeDeal() madeTransaction = true; hLeft = nullptr; hRight = nullptr; - if(resoursesPanelPlayer) - resoursesPanelPlayer->deselect(); - if(resoursesPanelMarket) - resoursesPanelMarket->deselect(); + for(auto & panel : tradePanels) + panel->deselect(); selectionChanged(true); }