From e5c532beb4e0b372ad72b39b955609db6bf71435 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 17 Dec 2023 16:30:19 +0200 Subject: [PATCH] gesture for quick backpack window --- client/widgets/CArtifactHolder.cpp | 14 ++++ client/widgets/CArtifactHolder.h | 3 + client/widgets/CArtifactsOfHeroAltar.cpp | 4 +- client/widgets/CArtifactsOfHeroBackpack.cpp | 81 ++++++++++++++------- client/widgets/CArtifactsOfHeroBackpack.h | 11 ++- client/widgets/CArtifactsOfHeroBase.cpp | 23 +++++- client/widgets/CArtifactsOfHeroBase.h | 9 ++- client/widgets/CArtifactsOfHeroKingdom.cpp | 9 ++- client/widgets/CArtifactsOfHeroMain.cpp | 5 +- client/widgets/CArtifactsOfHeroMarket.cpp | 4 +- client/widgets/CWindowWithArtifacts.cpp | 39 ++++++++-- client/widgets/CWindowWithArtifacts.h | 5 +- client/windows/CHeroBackpackWindow.cpp | 52 +++++++------ client/windows/CHeroBackpackWindow.h | 10 ++- lib/CArtifactInstance.cpp | 3 - 15 files changed, 188 insertions(+), 84 deletions(-) diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index 162cfdff5..544b6adff 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -192,6 +192,15 @@ void CArtPlace::showPopupWindow(const Point & cursorPosition) 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) { CIntObject::showAll(to); @@ -226,6 +235,11 @@ 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 4acfe86b8..fafc50e50 100644 --- a/client/widgets/CArtifactHolder.h +++ b/client/widgets/CArtifactHolder.h @@ -46,8 +46,10 @@ public: 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; @@ -57,6 +59,7 @@ protected: bool locked; ClickFunctor clickPressedCallback; ClickFunctor showPopupCallback; + ClickFunctor gestureCallback; void setInternals(const CArtifactInstance * artInst); }; diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index e5eda3c3d..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, _2), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2), + 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; diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp index 4353c0ff8..e8387528a 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.cpp +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -23,18 +23,18 @@ #include "../../CCallback.h" -CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack() +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax) + : slotsColumnsMax(slotsColumnsMax) + , slotsRowsMax(slotsRowsMax) { setRedrawParent(true); } -CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position) - : CArtifactsOfHeroBackpack() +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack() + : CArtifactsOfHeroBackpack(8, 8) { - pos += position; - const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); - auto visibleCapacityMax = slots_rows_max * slots_columns_max; + auto visibleCapacityMax = slotsRowsMax * slotsColumnsMax; if(backpackCap >= 0) visibleCapacityMax = visibleCapacityMax > backpackCap ? backpackCap : visibleCapacityMax; @@ -75,7 +75,7 @@ void CArtifactsOfHeroBackpack::updateBackpackSlots() size_t CArtifactsOfHeroBackpack::getActiveSlotRowsNum() { - return (curHero->artifactsInBackpack.size() + slots_columns_max - 1) / slots_columns_max; + return (curHero->artifactsInBackpack.size() + slotsColumnsMax - 1) / slotsColumnsMax; } size_t CArtifactsOfHeroBackpack::getSlotsNum() @@ -91,13 +91,13 @@ void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider) size_t artPlaceIdx = 0; for(auto & artPlace : backpack) { - const auto pos = Point(slotSizeWithMargin * (artPlaceIdx % slots_columns_max), - slotSizeWithMargin * (artPlaceIdx / slots_columns_max)); + 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::leftClickArtPlace, this, _1, _2)); - artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2)); + artPlace->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2)); + artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2)); artPlaceIdx++; } @@ -109,27 +109,36 @@ void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider) }; CListBoxWithCallback::MovedPosCallback posMoved = [this](size_t pos) -> void { - scrollBackpack(static_cast(pos) * slots_columns_max - backpackPos); + scrollBackpack(static_cast(pos) * slotsColumnsMax - backpackPos); }; backpackListBox = std::make_shared( - posMoved, onCreate, Point(0, 0), Point(0, 0), slots_rows_max, 0, 0, 1, - Rect(slots_columns_max * slotSizeWithMargin + sliderPosOffsetX, 0, slots_rows_max * slotSizeWithMargin - 2, 0)); + posMoved, onCreate, Point(0, 0), Point(0, 0), slotsRowsMax, 0, 0, 1, + Rect(slotsColumnsMax * slotSizeWithMargin + sliderPosOffsetX, 0, slotsRowsMax * slotSizeWithMargin - 2, 0)); } - pos.w = slots > slots_columns_max ? slots_columns_max : slots; + 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 = slots / slots_columns_max; - if(slots % slots_columns_max != 0) - pos.h += 1; - pos.h *= slotSizeWithMargin; + pos.h = calcRows(slots) * slotSizeWithMargin; } -CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const Point & position, const ArtifactPosition filterBySlot) +size_t CArtifactsOfHeroBackpack::calcRows(size_t slots) { - pos += position; + 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; @@ -153,12 +162,12 @@ void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero) scrollInSlotSpellId = artInSlot->getScrollSpellID(); } - std::map filteredArts; + 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->artType, slotInfo.artifact)); + filteredArts.insert(std::pair(slotInfo.artifact->getTypeId(), slotInfo.artifact)); } std::map filteredScrolls; @@ -173,7 +182,10 @@ void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero) } backpack.clear(); - initAOHbackpack(filteredArts.size() + filteredScrolls.size(), false); + 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); @@ -186,3 +198,22 @@ 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 7e1850f10..f8598fcd9 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.h +++ b/client/widgets/CArtifactsOfHeroBackpack.h @@ -22,8 +22,8 @@ class CListBoxWithCallback; class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase { public: + CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax); CArtifactsOfHeroBackpack(); - CArtifactsOfHeroBackpack(const Point & position); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickUpArtifact(CArtPlace & artPlace); void scrollBackpack(int offset) override; @@ -34,20 +34,23 @@ public: protected: std::shared_ptr backpackListBox; std::vector> backpackSlotsBackgrounds; - const size_t slots_columns_max = 8; - const size_t slots_rows_max = 8; + size_t slotsColumnsMax; + size_t slotsRowsMax; const int slotSizeWithMargin = 46; const int sliderPosOffsetX = 5; void initAOHbackpack(size_t slots, bool slider); + size_t calcRows(size_t slots); }; class CArtifactsOfHeroQuickBackpack : public CArtifactsOfHeroBackpack { public: - CArtifactsOfHeroQuickBackpack(const Point & position, const ArtifactPosition filterBySlot); + 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 9c3d7665c..520e3b1a1 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -95,18 +95,24 @@ void CArtifactsOfHeroBase::init( setRedrawParent(true); } -void CArtifactsOfHeroBase::leftClickArtPlace(CArtPlace & artPlace, const Point & cursorPosition) +void CArtifactsOfHeroBase::clickPrassedArtPlace(CArtPlace & artPlace, const Point & cursorPosition) { - if(leftClickCallback) - leftClickCallback(*this, artPlace, cursorPosition); + if(clickPressedCallback) + clickPressedCallback(*this, artPlace, cursorPosition); } -void CArtifactsOfHeroBase::rightClickArtPlace(CArtPlace & artPlace, const Point & cursorPosition) +void CArtifactsOfHeroBase::showPopupArtPlace(CArtPlace & artPlace, const Point & cursorPosition) { if(showPopupCallback) showPopupCallback(*this, artPlace, cursorPosition); } +void CArtifactsOfHeroBase::gestureArtPlace(CArtPlace & artPlace, const Point & cursorPosition) +{ + if(gestureCallback) + gestureCallback(*this, artPlace, cursorPosition); +} + void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero) { curHero = 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 aba6b152e..f124146ef 100644 --- a/client/widgets/CArtifactsOfHeroBase.h +++ b/client/widgets/CArtifactsOfHeroBase.h @@ -24,14 +24,16 @@ public: 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(CArtPlace & artPlace, const Point & cursorPosition); - virtual void rightClickArtPlace(CArtPlace & artPlace, const Point & cursorPosition); + 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 e174650c6..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->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1, _2)); - artPlace.second->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2)); + 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->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1, _2)); - artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2)); + 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)); diff --git a/client/widgets/CArtifactsOfHeroMain.cpp b/client/widgets/CArtifactsOfHeroMain.cpp index af834a1e0..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, _2), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2), + 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() diff --git a/client/widgets/CArtifactsOfHeroMarket.cpp b/client/widgets/CArtifactsOfHeroMarket.cpp index b172e4e77..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, _2), - std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1, _2), + 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/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index 360013438..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, _3); - artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2, _3); - 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, CArtPlace & artPlace, const Point & cursorPosition) +void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) { const auto artSetWeak = findAOHbyRef(artsInst); assert(artSetWeak.has_value()); @@ -217,7 +219,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst }, artSetWeak.value()); } -void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) +void CWindowWithArtifacts::showPopupArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) { const auto artSetWeak = findAOHbyRef(artsInst); assert(artSetWeak.has_value()); @@ -262,6 +264,29 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns }, 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()); +} + void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc) { updateSlots(); diff --git a/client/widgets/CWindowWithArtifacts.h b/client/widgets/CWindowWithArtifacts.h index 5645c8221..2cd2ddea4 100644 --- a/client/widgets/CWindowWithArtifacts.h +++ b/client/widgets/CWindowWithArtifacts.h @@ -33,8 +33,9 @@ public: void addCloseCallback(CloseCallback callback); const CGHeroInstance * getHeroPickedArtifact(); const CArtifactInstance * getPickedArtifact(); - void leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition); - void rightClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition); + 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 7e66d09f9..82186774d 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -19,34 +19,22 @@ #include "render/Canvas.h" #include "CPlayerInterface.h" -CHeroBackpackWindow::CHeroBackpackWindow() +CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) : CWindowObject((EOptions)0) { OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); stretchedBackground = std::make_shared(ImagePath::builtin("DIBOXBCK"), Rect(0, 0, 0, 0)); -} - -CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) - : CHeroBackpackWindow() -{ - OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); - - arts = std::make_shared(Point(windowMargin, windowMargin)); + arts = std::make_shared(); + arts->moveBy(Point(windowMargin, windowMargin)); addSetAndCallbacks(arts); arts->setHero(hero); addCloseCallback(std::bind(&CHeroBackpackWindow::close, this)); - - init(); - center(); -} - -void CHeroBackpackWindow::init() -{ quitButton = std::make_shared(Point(), AnimationPath::builtin("IOKAY32.def"), CButton::tooltip(""), [this]() { close(); }, EShortcut::GLOBAL_RETURN); 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(); } void CHeroBackpackWindow::showAll(Canvas & to) @@ -56,26 +44,44 @@ void CHeroBackpackWindow::showAll(Canvas & to) } CHeroQuickBackpackWindow::CHeroQuickBackpackWindow(const CGHeroInstance * hero, ArtifactPosition targetSlot) - : CHeroBackpackWindow() + : CWindowObject((EOptions)0) { OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); - auto artsQuickBp = std::make_shared(Point(windowMargin, windowMargin), targetSlot); - addSetAndCallbacks(static_cast>(artsQuickBp)); - arts = artsQuickBp; + 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; +} - init(); +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; } - - CHeroBackpackWindow::showAll(to); + 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 b8998867a..894d13343 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -17,7 +17,6 @@ class CFilledTexture; class CHeroBackpackWindow : public CWindowObject, public CWindowWithArtifacts { public: - CHeroBackpackWindow(); CHeroBackpackWindow(const CGHeroInstance * hero); protected: @@ -26,15 +25,20 @@ protected: std::shared_ptr stretchedBackground; const int windowMargin = 5; - void init(); void showAll(Canvas & to) override; }; -class CHeroQuickBackpackWindow : public CHeroBackpackWindow +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/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 5c2f7a31b..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(); }