diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index 334cd9f6e..544b6adff 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -139,7 +139,7 @@ void CCommanderArtPlace::clickPressed(const Point & cursorPosition) LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {}); } -void CCommanderArtPlace::showPopupWindow(const Point & cursorPosition) +void CCommanderArtPlace::showPopupWindow(const Point& cursorPosition) { if(ourArt && text.size()) CArtPlace::showPopupWindow(cursorPosition); @@ -180,16 +180,25 @@ bool CArtPlace::isSelected() const return selection->visible; } -void CHeroArtPlace::clickPressed(const Point & cursorPosition) +void CArtPlace::clickPressed(const Point & cursorPosition) { - if(leftClickCallback) - leftClickCallback(*this); + if(clickPressedCallback) + clickPressedCallback(*this, cursorPosition); } -void CHeroArtPlace::showPopupWindow(const Point & cursorPosition) +void CArtPlace::showPopupWindow(const Point & cursorPosition) { if(showPopupCallback) - showPopupCallback(*this); + showPopupCallback(*this, cursorPosition); +} + +void CArtPlace::gesture(bool on, const Point & initialPosition, const Point & finalPosition) +{ + if(!on) + return; + + if(gestureCallback) + gestureCallback(*this, initialPosition); } void CArtPlace::showAll(Canvas & to) @@ -216,6 +225,21 @@ void CArtPlace::setArtifact(const CArtifactInstance * art) } } +void CArtPlace::setClickPressedCallback(ClickFunctor callback) +{ + clickPressedCallback = callback; +} + +void CArtPlace::setShowPopupCallback(ClickFunctor callback) +{ + showPopupCallback = callback; +} + +void CArtPlace::setGestureCallback(ClickFunctor callback) +{ + gestureCallback = callback; +} + void CHeroArtPlace::addCombinedArtInfo(std::map & arts) { for(const auto & combinedArt : arts) diff --git a/client/widgets/CArtifactHolder.h b/client/widgets/CArtifactHolder.h index 43bc4e729..fafc50e50 100644 --- a/client/widgets/CArtifactHolder.h +++ b/client/widgets/CArtifactHolder.h @@ -32,14 +32,24 @@ public: class CArtPlace : public LRClickableAreaWTextComp { public: + using ClickFunctor = std::function; + + ArtifactPosition slot; + CArtPlace(Point position, const CArtifactInstance * art = nullptr); - const CArtifactInstance* getArt(); + const CArtifactInstance * getArt(); void lockSlot(bool on); bool isLocked() const; void selectSlot(bool on); bool isSelected() const; void showAll(Canvas & to) override; void setArtifact(const CArtifactInstance * art); + void setClickPressedCallback(ClickFunctor callback); + void setShowPopupCallback(ClickFunctor callback); + void setGestureCallback(ClickFunctor callback); + void clickPressed(const Point & cursorPosition) override; + void showPopupWindow(const Point & cursorPosition) override; + void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; protected: std::shared_ptr image; @@ -47,6 +57,9 @@ protected: int imageIndex; std::shared_ptr selection; bool locked; + ClickFunctor clickPressedCallback; + ClickFunctor showPopupCallback; + ClickFunctor gestureCallback; void setInternals(const CArtifactInstance * artInst); }; @@ -68,15 +81,7 @@ public: class CHeroArtPlace: public CArtPlace { public: - using ClickFunctor = std::function; - - ArtifactPosition slot; - ClickFunctor leftClickCallback; - ClickFunctor showPopupCallback; - CHeroArtPlace(Point position, const CArtifactInstance * art = nullptr); - void clickPressed(const Point & cursorPosition) override; - void showPopupWindow(const Point & cursorPosition) override; void addCombinedArtInfo(std::map & arts); }; diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index a104974a2..bda990634 100644 --- a/client/widgets/CArtifactsOfHeroAltar.cpp +++ b/client/widgets/CArtifactsOfHeroAltar.cpp @@ -23,8 +23,8 @@ CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) : visibleArtSet(ArtBearer::ArtBearer::HERO) { init( - std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1), + std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), + std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), position, std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1)); pickedArtFromSlot = ArtifactPosition::PRE_FIRST; @@ -69,7 +69,7 @@ void CArtifactsOfHeroAltar::scrollBackpack(int offset) redraw(); } -void CArtifactsOfHeroAltar::pickUpArtifact(CHeroArtPlace & artPlace) +void CArtifactsOfHeroAltar::pickUpArtifact(CArtPlace & artPlace) { if(const auto art = artPlace.getArt()) { diff --git a/client/widgets/CArtifactsOfHeroAltar.h b/client/widgets/CArtifactsOfHeroAltar.h index 83fd2b6f4..2dd81d68c 100644 --- a/client/widgets/CArtifactsOfHeroAltar.h +++ b/client/widgets/CArtifactsOfHeroAltar.h @@ -26,7 +26,7 @@ public: void updateWornSlots() override; void updateBackpackSlots() override; void scrollBackpack(int offset) override; - void pickUpArtifact(CHeroArtPlace & artPlace); + void pickUpArtifact(CArtPlace & artPlace); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickedArtMoveToAltar(const ArtifactPosition & slot); void deleteFromVisible(const CArtifactInstance * artInst); diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp index 6a487799c..e8387528a 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.cpp +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -17,60 +17,28 @@ #include "ObjectLists.h" #include "../CPlayerInterface.h" +#include "../../lib/ArtifactUtils.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/networkPacks/ArtifactLocation.h" #include "../../CCallback.h" -CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position) +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax) + : slotsColumnsMax(slotsColumnsMax) + , slotsRowsMax(slotsRowsMax) { - OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); - pos += position; setRedrawParent(true); +} +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack() + : CArtifactsOfHeroBackpack(8, 8) +{ const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); - auto visibleCapacityMax = HERO_BACKPACK_WINDOW_SLOT_ROWS * HERO_BACKPACK_WINDOW_SLOT_COLUMNS; + auto visibleCapacityMax = slotsRowsMax * slotsColumnsMax; if(backpackCap >= 0) visibleCapacityMax = visibleCapacityMax > backpackCap ? backpackCap : visibleCapacityMax; - backpack.resize(visibleCapacityMax); - size_t artPlaceIdx = 0; - for(auto & artPlace : backpack) - { - const auto pos = Point(slotSizeWithMargin * (artPlaceIdx % HERO_BACKPACK_WINDOW_SLOT_COLUMNS), - slotSizeWithMargin * (artPlaceIdx / HERO_BACKPACK_WINDOW_SLOT_COLUMNS)); - backpackSlotsBackgrounds.emplace_back(std::make_shared(ImagePath::builtin("heroWindow/artifactSlotEmpty"), pos)); - artPlace = std::make_shared(pos); - artPlace->setArtifact(nullptr); - artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1); - artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1); - artPlaceIdx++; - } - - if(backpackCap < 0 || visibleCapacityMax < backpackCap) - { - auto onCreate = [](size_t index) -> std::shared_ptr - { - return std::make_shared(); - }; - CListBoxWithCallback::MovedPosCallback posMoved = [this](size_t pos) -> void - { - scrollBackpack(static_cast(pos) * HERO_BACKPACK_WINDOW_SLOT_COLUMNS - backpackPos); - }; - backpackListBox = std::make_shared( - posMoved, onCreate, Point(0, 0), Point(0, 0), HERO_BACKPACK_WINDOW_SLOT_ROWS, 0, 0, 1, - Rect(HERO_BACKPACK_WINDOW_SLOT_COLUMNS * slotSizeWithMargin + sliderPosOffsetX, 0, HERO_BACKPACK_WINDOW_SLOT_ROWS * slotSizeWithMargin - 2, 0)); - } - - pos.w = visibleCapacityMax > HERO_BACKPACK_WINDOW_SLOT_COLUMNS ? HERO_BACKPACK_WINDOW_SLOT_COLUMNS : visibleCapacityMax; - pos.w *= slotSizeWithMargin; - if(backpackListBox) - pos.w += sliderPosOffsetX + 16; // 16 is slider width. TODO: get it from CListBox directly; - - pos.h = (visibleCapacityMax / HERO_BACKPACK_WINDOW_SLOT_COLUMNS); - if(visibleCapacityMax % HERO_BACKPACK_WINDOW_SLOT_COLUMNS != 0) - pos.h += 1; - pos.h *= slotSizeWithMargin; + initAOHbackpack(visibleCapacityMax, backpackCap < 0 || visibleCapacityMax < backpackCap); } void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) @@ -78,7 +46,7 @@ void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, co LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); } -void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace) +void CArtifactsOfHeroBackpack::pickUpArtifact(CArtPlace & artPlace) { LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); @@ -107,5 +75,145 @@ void CArtifactsOfHeroBackpack::updateBackpackSlots() size_t CArtifactsOfHeroBackpack::getActiveSlotRowsNum() { - return (curHero->artifactsInBackpack.size() + HERO_BACKPACK_WINDOW_SLOT_COLUMNS - 1) / HERO_BACKPACK_WINDOW_SLOT_COLUMNS; + return (curHero->artifactsInBackpack.size() + slotsColumnsMax - 1) / slotsColumnsMax; } + +size_t CArtifactsOfHeroBackpack::getSlotsNum() +{ + return backpack.size(); +} + +void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider) +{ + OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); + + backpack.resize(slots); + size_t artPlaceIdx = 0; + for(auto & artPlace : backpack) + { + const auto pos = Point(slotSizeWithMargin * (artPlaceIdx % slotsColumnsMax), + slotSizeWithMargin * (artPlaceIdx / slotsColumnsMax)); + backpackSlotsBackgrounds.emplace_back(std::make_shared(ImagePath::builtin("heroWindow/artifactSlotEmpty"), pos)); + artPlace = std::make_shared(pos); + artPlace->setArtifact(nullptr); + artPlace->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2)); + artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2)); + artPlaceIdx++; + } + + if(slider) + { + auto onCreate = [](size_t index) -> std::shared_ptr + { + return std::make_shared(); + }; + CListBoxWithCallback::MovedPosCallback posMoved = [this](size_t pos) -> void + { + scrollBackpack(static_cast(pos) * slotsColumnsMax - backpackPos); + }; + backpackListBox = std::make_shared( + posMoved, onCreate, Point(0, 0), Point(0, 0), slotsRowsMax, 0, 0, 1, + Rect(slotsColumnsMax * slotSizeWithMargin + sliderPosOffsetX, 0, slotsRowsMax * slotSizeWithMargin - 2, 0)); + } + + pos.w = slots > slotsColumnsMax ? slotsColumnsMax : slots; + pos.w *= slotSizeWithMargin; + if(slider) + pos.w += sliderPosOffsetX + 16; // 16 is slider width. TODO: get it from CListBox directly; + pos.h = calcRows(slots) * slotSizeWithMargin; +} + +size_t CArtifactsOfHeroBackpack::calcRows(size_t slots) +{ + size_t rows = 0; + if(slotsColumnsMax != 0) + { + rows = slots / slotsColumnsMax; + if(slots % slotsColumnsMax != 0) + rows += 1; + } + return rows; +} + +CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot) + : CArtifactsOfHeroBackpack(0, 0) +{ + assert(filterBySlot != ArtifactPosition::FIRST_AVAILABLE); + + if(!ArtifactUtils::isSlotEquipment(filterBySlot)) + return; + + this->filterBySlot = filterBySlot; +} + +void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero) +{ + if(curHero == hero) + return; + + curHero = hero; + if(curHero) + { + ArtifactID artInSlotId = ArtifactID::NONE; + SpellID scrollInSlotSpellId = SpellID::NONE; + if(auto artInSlot = curHero->getArt(filterBySlot)) + { + artInSlotId = artInSlot->getTypeId(); + scrollInSlotSpellId = artInSlot->getScrollSpellID(); + } + + std::map filteredArts; + for(auto & slotInfo : curHero->artifactsInBackpack) + if(slotInfo.artifact->getTypeId() != artInSlotId && !slotInfo.artifact->isScroll() && + slotInfo.artifact->artType->canBePutAt(curHero, filterBySlot, true)) + { + filteredArts.insert(std::pair(slotInfo.artifact->getTypeId(), slotInfo.artifact)); + } + + std::map filteredScrolls; + if(filterBySlot == ArtifactPosition::MISC1 || filterBySlot == ArtifactPosition::MISC2 || filterBySlot == ArtifactPosition::MISC3 || + filterBySlot == ArtifactPosition::MISC4 || filterBySlot == ArtifactPosition::MISC5) + { + for(auto & slotInfo : curHero->artifactsInBackpack) + { + if(slotInfo.artifact->isScroll() && slotInfo.artifact->getScrollSpellID() != scrollInSlotSpellId) + filteredScrolls.insert(std::pair(slotInfo.artifact->getScrollSpellID(), slotInfo.artifact)); + } + } + + backpack.clear(); + auto requiredSlots = filteredArts.size() + filteredScrolls.size(); + slotsColumnsMax = ceilf(sqrtf(requiredSlots)); + slotsRowsMax = calcRows(requiredSlots); + initAOHbackpack(requiredSlots, false); + auto artPlace = backpack.begin(); + for(auto & art : filteredArts) + setSlotData(*artPlace++, curHero->getSlotByInstance(art.second), *curHero); + for(auto & art : filteredScrolls) + setSlotData(*artPlace++, curHero->getSlotByInstance(art.second), *curHero); + } +} + +ArtifactPosition CArtifactsOfHeroQuickBackpack::getFilterSlot() +{ + return filterBySlot; +} + +void CArtifactsOfHeroQuickBackpack::selectSlotAt(const Point & position) +{ + for(auto & artPlace : backpack) + artPlace->selectSlot(artPlace->pos.isInside(position)); +} + +void CArtifactsOfHeroQuickBackpack::swapSelected() +{ + ArtifactLocation backpackLoc(curHero->id, ArtifactPosition::PRE_FIRST); + for(auto & artPlace : backpack) + if(artPlace->isSelected()) + { + backpackLoc.slot = artPlace->slot; + break; + } + if(backpackLoc.slot != ArtifactPosition::PRE_FIRST && filterBySlot != ArtifactPosition::PRE_FIRST && curHero) + swapArtifacts(backpackLoc, ArtifactLocation(curHero->id, filterBySlot)); +} \ No newline at end of file diff --git a/client/widgets/CArtifactsOfHeroBackpack.h b/client/widgets/CArtifactsOfHeroBackpack.h index ce51531ef..f8598fcd9 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.h +++ b/client/widgets/CArtifactsOfHeroBackpack.h @@ -22,18 +22,36 @@ class CListBoxWithCallback; class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase { public: - CArtifactsOfHeroBackpack(const Point & position); + CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax); + CArtifactsOfHeroBackpack(); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); - void pickUpArtifact(CHeroArtPlace & artPlace); + void pickUpArtifact(CArtPlace & artPlace); void scrollBackpack(int offset) override; void updateBackpackSlots() override; size_t getActiveSlotRowsNum(); + size_t getSlotsNum(); -private: +protected: std::shared_ptr backpackListBox; std::vector> backpackSlotsBackgrounds; - const size_t HERO_BACKPACK_WINDOW_SLOT_COLUMNS = 8; - const size_t HERO_BACKPACK_WINDOW_SLOT_ROWS = 8; + size_t slotsColumnsMax; + size_t slotsRowsMax; const int slotSizeWithMargin = 46; - const int sliderPosOffsetX = 10; + const int sliderPosOffsetX = 5; + + void initAOHbackpack(size_t slots, bool slider); + size_t calcRows(size_t slots); +}; + +class CArtifactsOfHeroQuickBackpack : public CArtifactsOfHeroBackpack +{ +public: + CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot); + void setHero(const CGHeroInstance * hero); + ArtifactPosition getFilterSlot(); + void selectSlotAt(const Point & position); + void swapSelected(); + +private: + ArtifactPosition filterBySlot; }; diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 319c40e2f..520e3b1a1 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -56,8 +56,8 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall } void CArtifactsOfHeroBase::init( - CHeroArtPlace::ClickFunctor lClickCallback, - CHeroArtPlace::ClickFunctor showPopupCallback, + CArtPlace::ClickFunctor lClickCallback, + CArtPlace::ClickFunctor showPopupCallback, const Point & position, BpackScrollFunctor scrollCallback) { @@ -78,14 +78,14 @@ void CArtifactsOfHeroBase::init( { artPlace.second->slot = artPlace.first; artPlace.second->setArtifact(nullptr); - artPlace.second->leftClickCallback = lClickCallback; - artPlace.second->showPopupCallback = showPopupCallback; + artPlace.second->setClickPressedCallback(lClickCallback); + artPlace.second->setShowPopupCallback(showPopupCallback); } for(auto artPlace : backpack) { artPlace->setArtifact(nullptr); - artPlace->leftClickCallback = lClickCallback; - artPlace->showPopupCallback = showPopupCallback; + artPlace->setClickPressedCallback(lClickCallback); + artPlace->setShowPopupCallback(showPopupCallback); } leftBackpackRoll = std::make_shared(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(-1);}, EShortcut::MOVE_LEFT); rightBackpackRoll = std::make_shared(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(+1);}, EShortcut::MOVE_RIGHT); @@ -95,16 +95,22 @@ void CArtifactsOfHeroBase::init( setRedrawParent(true); } -void CArtifactsOfHeroBase::leftClickArtPlace(CHeroArtPlace & artPlace) +void CArtifactsOfHeroBase::clickPrassedArtPlace(CArtPlace & artPlace, const Point & cursorPosition) { - if(leftClickCallback) - leftClickCallback(*this, artPlace); + if(clickPressedCallback) + clickPressedCallback(*this, artPlace, cursorPosition); } -void CArtifactsOfHeroBase::rightClickArtPlace(CHeroArtPlace & artPlace) +void CArtifactsOfHeroBase::showPopupArtPlace(CArtPlace & artPlace, const Point & cursorPosition) { if(showPopupCallback) - showPopupCallback(*this, artPlace); + showPopupCallback(*this, artPlace, cursorPosition); +} + +void CArtifactsOfHeroBase::gestureArtPlace(CArtPlace & artPlace, const Point & cursorPosition) +{ + if(gestureCallback) + gestureCallback(*this, artPlace, cursorPosition); } void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero) @@ -241,6 +247,15 @@ const CArtifactInstance * CArtifactsOfHeroBase::getPickedArtifact() return curHero->getArt(ArtifactPosition::TRANSITION_POS); } +void CArtifactsOfHeroBase::addGestureCallback(CArtPlace::ClickFunctor callback) +{ + for(auto & artPlace : artWorn) + { + artPlace.second->setGestureCallback(callback); + artPlace.second->addUsedEvents(GESTURE); + } +} + void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot, const CArtifactSet & artSet) { // Spurious call from artifactMoved in attempt to update hidden backpack slot diff --git a/client/widgets/CArtifactsOfHeroBase.h b/client/widgets/CArtifactsOfHeroBase.h index a85b8ebff..f124146ef 100644 --- a/client/widgets/CArtifactsOfHeroBase.h +++ b/client/widgets/CArtifactsOfHeroBase.h @@ -21,17 +21,19 @@ protected: public: using ArtPlaceMap = std::map; - using ClickFunctor = std::function; + using ClickFunctor = std::function; using PutBackPickedArtCallback = std::function; - ClickFunctor leftClickCallback; + ClickFunctor clickPressedCallback; ClickFunctor showPopupCallback; + ClickFunctor gestureCallback; CArtifactsOfHeroBase(); virtual void putBackPickedArtifact(); virtual void setPutBackPickedArtifactCallback(PutBackPickedArtCallback callback); - virtual void leftClickArtPlace(CHeroArtPlace & artPlace); - virtual void rightClickArtPlace(CHeroArtPlace & artPlace); + virtual void clickPrassedArtPlace(CArtPlace & artPlace, const Point & cursorPosition); + virtual void showPopupArtPlace(CArtPlace & artPlace, const Point & cursorPosition); + virtual void gestureArtPlace(CArtPlace & artPlace, const Point & cursorPosition); virtual void setHero(const CGHeroInstance * hero); virtual const CGHeroInstance * getHero() const; virtual void scrollBackpack(int offset); @@ -42,6 +44,7 @@ public: virtual void updateBackpackSlots(); virtual void updateSlot(const ArtifactPosition & slot); virtual const CArtifactInstance * getPickedArtifact(); + void addGestureCallback(CArtPlace::ClickFunctor callback); protected: const CGHeroInstance * curHero; diff --git a/client/widgets/CArtifactsOfHeroKingdom.cpp b/client/widgets/CArtifactsOfHeroKingdom.cpp index 14fd222f4..5d6e1e02b 100644 --- a/client/widgets/CArtifactsOfHeroKingdom.cpp +++ b/client/widgets/CArtifactsOfHeroKingdom.cpp @@ -30,14 +30,15 @@ CArtifactsOfHeroKingdom::CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vecto { artPlace.second->slot = artPlace.first; artPlace.second->setArtifact(nullptr); - artPlace.second->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1); - artPlace.second->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1); + artPlace.second->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2)); + artPlace.second->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2)); } + addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2)); for(auto artPlace : backpack) { artPlace->setArtifact(nullptr); - artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1); - artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1); + artPlace->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2)); + artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2)); } leftBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, -1)); rightBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, +1)); @@ -55,7 +56,7 @@ void CArtifactsOfHeroKingdom::swapArtifacts(const ArtifactLocation & srcLoc, con LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); } -void CArtifactsOfHeroKingdom::pickUpArtifact(CHeroArtPlace & artPlace) +void CArtifactsOfHeroKingdom::pickUpArtifact(CArtPlace & artPlace) { LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); diff --git a/client/widgets/CArtifactsOfHeroKingdom.h b/client/widgets/CArtifactsOfHeroKingdom.h index 84f6ad185..738b21074 100644 --- a/client/widgets/CArtifactsOfHeroKingdom.h +++ b/client/widgets/CArtifactsOfHeroKingdom.h @@ -24,5 +24,5 @@ public: std::shared_ptr leftScroll, std::shared_ptr rightScroll); ~CArtifactsOfHeroKingdom(); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); - void pickUpArtifact(CHeroArtPlace & artPlace); + void pickUpArtifact(CArtPlace & artPlace); }; \ No newline at end of file diff --git a/client/widgets/CArtifactsOfHeroMain.cpp b/client/widgets/CArtifactsOfHeroMain.cpp index b4ac981b0..326eff818 100644 --- a/client/widgets/CArtifactsOfHeroMain.cpp +++ b/client/widgets/CArtifactsOfHeroMain.cpp @@ -19,10 +19,11 @@ CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position) { init( - std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1), + std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), + std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), position, std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1)); + addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2)); } CArtifactsOfHeroMain::~CArtifactsOfHeroMain() @@ -35,7 +36,7 @@ void CArtifactsOfHeroMain::swapArtifacts(const ArtifactLocation & srcLoc, const LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); } -void CArtifactsOfHeroMain::pickUpArtifact(CHeroArtPlace & artPlace) +void CArtifactsOfHeroMain::pickUpArtifact(CArtPlace & artPlace) { LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); diff --git a/client/widgets/CArtifactsOfHeroMain.h b/client/widgets/CArtifactsOfHeroMain.h index 6e7253bbe..9e7f318dd 100644 --- a/client/widgets/CArtifactsOfHeroMain.h +++ b/client/widgets/CArtifactsOfHeroMain.h @@ -23,5 +23,5 @@ public: CArtifactsOfHeroMain(const Point & position); ~CArtifactsOfHeroMain(); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); - void pickUpArtifact(CHeroArtPlace & artPlace); + void pickUpArtifact(CArtPlace & artPlace); }; diff --git a/client/widgets/CArtifactsOfHeroMarket.cpp b/client/widgets/CArtifactsOfHeroMarket.cpp index 94d04f512..0f71aca12 100644 --- a/client/widgets/CArtifactsOfHeroMarket.cpp +++ b/client/widgets/CArtifactsOfHeroMarket.cpp @@ -15,8 +15,8 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position) { init( - std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1), + std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), + std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), position, std::bind(&CArtifactsOfHeroMarket::scrollBackpack, this, _1)); }; diff --git a/client/widgets/CArtifactsOfHeroMarket.h b/client/widgets/CArtifactsOfHeroMarket.h index c88ff0494..c8d34c399 100644 --- a/client/widgets/CArtifactsOfHeroMarket.h +++ b/client/widgets/CArtifactsOfHeroMarket.h @@ -14,7 +14,7 @@ class CArtifactsOfHeroMarket : public CArtifactsOfHeroBase { public: - std::function selectArtCallback; + std::function selectArtCallback; CArtifactsOfHeroMarket(const Point & position); void scrollBackpack(int offset) override; diff --git a/client/widgets/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index bf5ca043e..360d896de 100644 --- a/client/widgets/CWindowWithArtifacts.cpp +++ b/client/widgets/CWindowWithArtifacts.cpp @@ -23,6 +23,7 @@ #include "../windows/CHeroWindow.h" #include "../windows/CSpellWindow.h" #include "../windows/GUIClasses.h" +#include "../windows/CHeroBackpackWindow.h" #include "../CPlayerInterface.h" #include "../CGameInfo.h" @@ -39,18 +40,19 @@ void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet) void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr artSet) { - CArtifactsOfHeroBase::PutBackPickedArtCallback artPutBackHandler = []() -> void + CArtifactsOfHeroBase::PutBackPickedArtCallback artPutBackFunctor = []() -> void { CCS->curh->dragAndDropCursor(nullptr); }; addSet(artSet); - std::visit([this, artPutBackHandler](auto artSetWeak) + std::visit([this, artPutBackFunctor](auto artSetWeak) { auto artSet = artSetWeak.lock(); - artSet->leftClickCallback = std::bind(&CWindowWithArtifacts::leftClickArtPlaceHero, this, _1, _2); - artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2); - artSet->setPutBackPickedArtifactCallback(artPutBackHandler); + artSet->clickPressedCallback = std::bind(&CWindowWithArtifacts::clickPressedArtPlaceHero, this, _1, _2, _3); + artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::showPopupArtPlaceHero, this, _1, _2, _3); + artSet->gestureCallback = std::bind(&CWindowWithArtifacts::gestureArtPlaceHero, this, _1, _2, _3); + artSet->setPutBackPickedArtifactCallback(artPutBackFunctor); }, artSet); } @@ -77,7 +79,7 @@ const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact() return nullptr; } -void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CHeroArtPlace & artPlace) +void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) { const auto artSetWeak = findAOHbyRef(artsInst); assert(artSetWeak.has_value()); @@ -85,7 +87,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst if(artPlace.isLocked()) return; - const auto checkSpecialArts = [](const CGHeroInstance * hero, CHeroArtPlace & artPlace) -> bool + const auto checkSpecialArts = [](const CGHeroInstance * hero, CArtPlace & artPlace) -> bool { if(artPlace.getArt()->getTypeId() == ArtifactID::SPELLBOOK) { @@ -206,10 +208,18 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst } } } + else if constexpr(std::is_same_v>) + { + const auto hero = artSetPtr->getHero(); + artSetPtr->swapArtifacts(ArtifactLocation(hero->id, artPlace.slot), + ArtifactLocation(hero->id, artSetPtr->getFilterSlot())); + if(closeCallback) + closeCallback(); + } }, artSetWeak.value()); } -void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CHeroArtPlace & artPlace) +void CWindowWithArtifacts::showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) { const auto artSetWeak = findAOHbyRef(artsInst); assert(artSetWeak.has_value()); @@ -218,7 +228,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns return; std::visit( - [&artPlace](auto artSetWeak) -> void + [&artPlace, &cursorPosition](auto artSetWeak) -> void { const auto artSetPtr = artSetWeak.lock(); @@ -239,16 +249,40 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns return; } if(artPlace.text.size()) - artPlace.LRClickableAreaWTextComp::showPopupWindow(GH.getCursorPosition()); + artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition); } } // Altar window, Market window right click handler else if constexpr( std::is_same_v> || - std::is_same_v>) + std::is_same_v> || + std::is_same_v>) { if(artPlace.getArt() && artPlace.text.size()) - artPlace.LRClickableAreaWTextComp::showPopupWindow(GH.getCursorPosition()); + artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition); + } + }, artSetWeak.value()); +} + +void CWindowWithArtifacts::gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) +{ + const auto artSetWeak = findAOHbyRef(artsInst); + assert(artSetWeak.has_value()); + if(artPlace.isLocked()) + return; + + std::visit( + [&artPlace, cursorPosition](auto artSetWeak) -> void + { + const auto artSetPtr = artSetWeak.lock(); + if constexpr( + std::is_same_v> || + std::is_same_v>) + { + GH.windows().createAndPushWindow(artSetPtr->getHero(), artPlace.slot); + auto backpackWindow = GH.windows().topWindow(); + backpackWindow->moveTo(cursorPosition - Point(1, 1)); + backpackWindow->fitToScreen(15); } }, artSetWeak.value()); } diff --git a/client/widgets/CWindowWithArtifacts.h b/client/widgets/CWindowWithArtifacts.h index 777e4537d..2cd2ddea4 100644 --- a/client/widgets/CWindowWithArtifacts.h +++ b/client/widgets/CWindowWithArtifacts.h @@ -24,7 +24,8 @@ public: std::weak_ptr, std::weak_ptr, std::weak_ptr, - std::weak_ptr>; + std::weak_ptr, + std::weak_ptr>; using CloseCallback = std::function; void addSet(CArtifactsOfHeroPtr artSet); @@ -32,8 +33,9 @@ public: void addCloseCallback(CloseCallback callback); const CGHeroInstance * getHeroPickedArtifact(); const CArtifactInstance * getPickedArtifact(); - void leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CHeroArtPlace & artPlace); - void rightClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CHeroArtPlace & artPlace); + void clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition); + void showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition); + void gestureArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition); void artifactRemoved(const ArtifactLocation & artLoc) override; void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) override; diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp index a4ff6d1c8..82186774d 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -22,25 +22,19 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) : CWindowObject((EOptions)0) { - OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); - stretchedBackground = std::make_shared(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, 410, 425)); - - arts = std::make_shared(Point(windowMargin, windowMargin)); - arts->setHero(hero); + stretchedBackground = std::make_shared(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, 0, 0)); + arts = std::make_shared(); + arts->moveBy(Point(windowMargin, windowMargin)); addSetAndCallbacks(arts); - + arts->setHero(hero); addCloseCallback(std::bind(&CHeroBackpackWindow::close, this)); - quitButton = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), [this]() { close(); }, EShortcut::GLOBAL_RETURN); - - stretchedBackground->pos.w = arts->pos.w + 2 * windowMargin; - stretchedBackground->pos.h = arts->pos.h + quitButton->pos.h + 3 * windowMargin; - pos.w = stretchedBackground->pos.w; - pos.h = stretchedBackground->pos.h; + pos.w = stretchedBackground->pos.w = arts->pos.w + 2 * windowMargin; + pos.h = stretchedBackground->pos.h = arts->pos.h + quitButton->pos.h + 3 * windowMargin; + quitButton->moveTo(Point(pos.x + pos.w / 2 - quitButton->pos.w / 2, pos.y + arts->pos.h + 2 * windowMargin)); center(); - - quitButton->moveBy(Point(GH.screenDimensions().x / 2 - quitButton->pos.w / 2 - quitButton->pos.x, arts->pos.h + 2 * windowMargin)); } void CHeroBackpackWindow::showAll(Canvas & to) @@ -48,3 +42,46 @@ void CHeroBackpackWindow::showAll(Canvas & to) CIntObject::showAll(to); CMessage::drawBorder(PlayerColor(LOCPLINT->playerID), to.getInternalSurface(), pos.w+28, pos.h+29, pos.x-14, pos.y-15); } + +CHeroQuickBackpackWindow::CHeroQuickBackpackWindow(const CGHeroInstance * hero, ArtifactPosition targetSlot) + : CWindowObject((EOptions)0) +{ + OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); + + stretchedBackground = std::make_shared(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, 0, 0)); + arts = std::make_shared(targetSlot); + arts->moveBy(Point(windowMargin, windowMargin)); + addSetAndCallbacks(static_cast>(arts)); + arts->setHero(hero); + addCloseCallback(std::bind(&CHeroQuickBackpackWindow::close, this)); + addUsedEvents(GESTURE); + pos.w = stretchedBackground->pos.w = arts->pos.w + 2 * windowMargin; + pos.h = stretchedBackground->pos.h = arts->pos.h + windowMargin; +} + +void CHeroQuickBackpackWindow::gesture(bool on, const Point & initialPosition, const Point & finalPosition) +{ + if(on) + return; + + arts->swapSelected(); + close(); +} + +void CHeroQuickBackpackWindow::gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) +{ + arts->selectSlotAt(currentPosition); + redraw(); +} + +void CHeroQuickBackpackWindow::showAll(Canvas & to) +{ + if(arts->getSlotsNum() == 0) + { + // Dirty solution for closing that window + close(); + return; + } + CMessage::drawBorder(PlayerColor(LOCPLINT->playerID), to.getInternalSurface(), pos.w + 28, pos.h + 29, pos.x - 14, pos.y - 15); + CIntObject::showAll(to); +} diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h index 73d736b0a..894d13343 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -19,11 +19,26 @@ class CHeroBackpackWindow : public CWindowObject, public CWindowWithArtifacts public: CHeroBackpackWindow(const CGHeroInstance * hero); -private: +protected: std::shared_ptr arts; std::shared_ptr quitButton; std::shared_ptr stretchedBackground; - const int windowMargin = 10; + const int windowMargin = 5; + + void showAll(Canvas & to) override; +}; + +class CHeroQuickBackpackWindow : public CWindowObject, public CWindowWithArtifacts +{ +public: + CHeroQuickBackpackWindow(const CGHeroInstance * hero, ArtifactPosition targetSlot); + void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override; + void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override; + +private: + std::shared_ptr arts; + std::shared_ptr stretchedBackground; + const int windowMargin = 5; void showAll(Canvas & to) override; }; diff --git a/client/windows/CHeroWindow.h b/client/windows/CHeroWindow.h index 94e91ad33..b8ead7a20 100644 --- a/client/windows/CHeroWindow.h +++ b/client/windows/CHeroWindow.h @@ -111,6 +111,5 @@ public: void createBackpackWindow(); //friends - friend void CHeroArtPlace::clickPressed(const Point & cursorPosition); friend class CPlayerInterface; }; diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index d5a728dcb..c27ec0775 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -331,7 +331,7 @@ void CTradeWindow::setMode(EMarketMode Mode) } } -void CTradeWindow::artifactSelected(CHeroArtPlace *slot) +void CTradeWindow::artifactSelected(CArtPlace * slot) { assert(mode == EMarketMode::ARTIFACT_RESOURCE); items[1][0]->setArtInstance(slot->getArt()); diff --git a/client/windows/CTradeWindow.h b/client/windows/CTradeWindow.h index 04ea7529c..85698c295 100644 --- a/client/windows/CTradeWindow.h +++ b/client/windows/CTradeWindow.h @@ -40,7 +40,7 @@ public: void getPositionsFor(std::vector &poss, bool Left, EType type) const; void setMode(EMarketMode Mode); //mode setter - void artifactSelected(CHeroArtPlace *slot); //used when selling artifacts -> called when user clicked on artifact slot + void artifactSelected(CArtPlace * slot); //used when selling artifacts -> called when user clicked on artifact slot virtual void selectionChanged(bool side) = 0; //true == left virtual Point selectionOffset(bool Left) const = 0; virtual std::string updateSlotSubtitle(bool Left) const = 0; diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index c790ca379..0928b2308 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -64,10 +64,7 @@ SpellID CScrollArtifactInstance::getScrollSpellID() const auto artInst = static_cast(this); const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); if(!bonus) - { - logMod->warn("Warning: %s doesn't bear any spell!", artInst->nodeName()); return SpellID::NONE; - } return bonus->subtype.as(); } @@ -165,6 +162,11 @@ bool CArtifactInstance::isCombined() const return artType->isCombined(); } +bool CArtifactInstance::isScroll() const +{ + return artType->isScroll(); +} + void CArtifactInstance::putAt(CArtifactSet & set, const ArtifactPosition slot) { auto placementMap = set.putArtifact(slot, this); diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index d72397afe..fbee8c8fc 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -87,6 +87,7 @@ public: bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE, bool assumeDestRemoved = false) const; bool isCombined() const; + bool isScroll() const; void putAt(CArtifactSet & set, const ArtifactPosition slot); void removeFrom(CArtifactSet & set, const ArtifactPosition slot); void move(CArtifactSet & srcSet, const ArtifactPosition srcSlot, CArtifactSet & dstSet, const ArtifactPosition dstSlot);