From 3ea6f530adf42fc0efa3dfaf42cffd9e5194d4ce Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 6 Jul 2023 21:37:18 +0300 Subject: [PATCH 1/4] backpack window initial --- client/widgets/CArtifactsOfHeroBase.cpp | 4 -- client/widgets/CArtifactsOfHeroBase.h | 2 +- client/widgets/CWindowWithArtifacts.cpp | 5 ++ client/widgets/CWindowWithArtifacts.h | 1 + client/windows/CTradeWindow.cpp | 62 +++++++++---------------- client/windows/CTradeWindow.h | 3 +- 6 files changed, 31 insertions(+), 46 deletions(-) diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 8c9039770..38e9371f9 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -32,10 +32,6 @@ CArtifactsOfHeroBase::CArtifactsOfHeroBase() CArtifactsOfHeroBase::~CArtifactsOfHeroBase() { - // TODO: cursor handling is CWindowWithArtifacts level. Should be moved when trading, kingdom and hero window are reworked - // This will interfere with the implementation of a separate backpack window - CCS->curh->dragAndDropCursor(nullptr); - // Artifact located in artifactsTransitionPos should be returned if(getPickedArtifact()) { diff --git a/client/widgets/CArtifactsOfHeroBase.h b/client/widgets/CArtifactsOfHeroBase.h index d21e5983e..743a98254 100644 --- a/client/widgets/CArtifactsOfHeroBase.h +++ b/client/widgets/CArtifactsOfHeroBase.h @@ -21,7 +21,6 @@ public: using ArtPlaceMap = std::map; using ClickHandler = std::function; - const CGHeroInstance * curHero; ClickHandler leftClickCallback; ClickHandler rightClickCallback; @@ -42,6 +41,7 @@ public: virtual const CArtifactInstance * getPickedArtifact(); protected: + const CGHeroInstance * curHero; ArtPlaceMap artWorn; std::vector backpack; std::shared_ptr leftBackpackRoll; diff --git a/client/widgets/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index b421ea769..45bcc7e54 100644 --- a/client/widgets/CWindowWithArtifacts.cpp +++ b/client/widgets/CWindowWithArtifacts.cpp @@ -26,6 +26,11 @@ #include "../../lib/CGeneralTextHandler.h" #include "../../lib/mapObjects/CGHeroInstance.h" +CWindowWithArtifacts::~CWindowWithArtifacts() +{ + CCS->curh->dragAndDropCursor(nullptr); +} + void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet) { artSets.emplace_back(artSet); diff --git a/client/widgets/CWindowWithArtifacts.h b/client/widgets/CWindowWithArtifacts.h index e7517d9be..51df78be4 100644 --- a/client/widgets/CWindowWithArtifacts.h +++ b/client/widgets/CWindowWithArtifacts.h @@ -24,6 +24,7 @@ public: std::weak_ptr, std::weak_ptr>; + virtual ~CWindowWithArtifacts(); void addSet(CArtifactsOfHeroPtr artSet); const CGHeroInstance * getHeroPickedArtifact(); const CArtifactInstance * getPickedArtifact(); diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index 4291f2bff..d52f3fbc3 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -180,24 +180,23 @@ void CTradeWindow::CTradeableItem::clickPressed(const Point & cursorPosition) CAltarWindow *aw = static_cast(mw); const auto pickedArtInst = aw->getPickedArtifact(); - auto artifactsOfHero = std::dynamic_pointer_cast(aw->arts); if(pickedArtInst) { - artifactsOfHero->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS); + aw->arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS); aw->moveArtToAltar(this->shared_from_this(), pickedArtInst); } else if(const CArtifactInstance *art = getArtInstance()) { - const auto hero = artifactsOfHero->getHero(); + const auto hero = aw->arts->getHero(); const auto slot = hero->getSlotByInstance(art); assert(slot != ArtifactPosition::PRE_FIRST); LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero, slot), ArtifactLocation(hero, ArtifactPosition::TRANSITION_POS)); - artifactsOfHero->pickedArtFromSlot = slot; - artifactsOfHero->artifactsOnAltar.erase(art); + aw->arts->pickedArtFromSlot = slot; + aw->arts->artifactsOnAltar.erase(art); setID(-1); subtitle.clear(); - aw->deal->block(!artifactsOfHero->artifactsOnAltar.size()); + aw->deal->block(!aw->arts->artifactsOnAltar.size()); } aw->calcTotalExp(); @@ -374,34 +373,10 @@ void CTradeWindow::initItems(bool Left) int xOffset = 0, yOffset = 0; if(mode == EMarketMode::ARTIFACT_RESOURCE) { - xOffset = -361; - yOffset = +46; - auto item = std::make_shared(Point(137, 469), itemsType[Left], -1, 1, 0); item->recActions &= ~(UPDATE | SHOWALL); items[Left].push_back(item); } - else //ARTIFACT_EXP - { - xOffset = -365; - yOffset = -12; - } - - if(mode == EMarketMode::ARTIFACT_RESOURCE) - { - auto artifactsOfHero = std::make_shared(Point(xOffset, yOffset)); - artifactsOfHero->selectArtCallback = std::bind(&CTradeWindow::artifactSelected, this, _1); - artifactsOfHero->setHero(hero); - addSet(artifactsOfHero); - arts = artifactsOfHero; - } - else - { - auto artifactsOfHero = std::make_shared(Point(xOffset, yOffset)); - artifactsOfHero->setHero(hero); - addSet(artifactsOfHero); - arts = artifactsOfHero; - } } else { @@ -701,7 +676,13 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta } titleLabel = std::make_shared(300, 27, FONT_BIG, ETextAlignment::CENTER, Colors::YELLOW, title); - + if(mode == EMarketMode::ARTIFACT_RESOURCE) + { + arts = std::make_shared(Point(-361, 46)); + arts->selectArtCallback = std::bind(&CTradeWindow::artifactSelected, this, _1); + arts->setHero(hero); + addSet(arts); + } initItems(false); initItems(true); @@ -1133,6 +1114,10 @@ CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, sacrificeBackpack = std::make_shared(Point(147, 520), "ALTEMBK.DEF", CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this)); sacrificeBackpack->block(hero->artifactsInBackpack.empty()); + arts = std::make_shared(Point(-365, -12)); + arts->setHero(hero); + addSet(arts); + initItems(true); initItems(false); artIcon = std::make_shared("ARTIFACT", 0, 0, 281, 442); @@ -1234,15 +1219,14 @@ void CAltarWindow::makeDeal() else { std::vector positions; - auto artifactsOfHero = std::dynamic_pointer_cast(arts); - for(const CArtifactInstance * art : artifactsOfHero->artifactsOnAltar) + for(const CArtifactInstance * art : arts->artifactsOnAltar) { positions.push_back(hero->getSlotByInstance(art)); } std::sort(positions.begin(), positions.end(), std::greater<>()); LOCPLINT->cb->trade(market, mode, positions, {}, {}, hero); - artifactsOfHero->artifactsOnAltar.clear(); + arts->artifactsOnAltar.clear(); for(auto item : items[0]) { @@ -1279,13 +1263,12 @@ void CAltarWindow::SacrificeAll() } else { - auto artifactsOfHero = std::dynamic_pointer_cast(arts); - for(const auto & aw : artifactsOfHero->visibleArtSet.artifactsWorn) + for(const auto & aw : arts->visibleArtSet.artifactsWorn) { if(!aw.second.locked) moveArtToAltar(nullptr, aw.second.artifact); } - artifactsOfHero->updateWornSlots(); + arts->updateWornSlots(); SacrificeBackpack(); } redraw(); @@ -1501,9 +1484,8 @@ bool CAltarWindow::putOnAltar(std::shared_ptr altarSlot, const C market->getOffer(art->artType->getId(), 0, dmp, val, EMarketMode::ARTIFACT_EXP); val = static_cast(hero->calculateXp(val)); - auto artsAltar = std::dynamic_pointer_cast(arts); - artsAltar->artifactsOnAltar.insert(art); - artsAltar->deleteFromVisible(art); + arts->artifactsOnAltar.insert(art); + arts->deleteFromVisible(art); altarSlot->setArtInstance(art); altarSlot->subtitle = std::to_string(val); diff --git a/client/windows/CTradeWindow.h b/client/windows/CTradeWindow.h index c8343deb4..396b6e435 100644 --- a/client/windows/CTradeWindow.h +++ b/client/windows/CTradeWindow.h @@ -67,7 +67,6 @@ public: const IMarket * market; const CGHeroInstance * hero; - std::shared_ptr arts; //all indexes: 1 = left, 0 = right std::array>, 2> items; @@ -117,6 +116,7 @@ protected: class CMarketplaceWindow : public CTradeWindow { std::shared_ptr titleLabel; + std::shared_ptr arts; bool printButtonFor(EMarketMode::EMarketMode M) const; @@ -155,6 +155,7 @@ public: std::shared_ptr sacrificeBackpack; std::shared_ptr expToLevel; std::shared_ptr expOnAltar; + std::shared_ptr arts; CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, EMarketMode::EMarketMode Mode); ~CAltarWindow(); From 9427de6344aed643a8d65963d0ead43ff6172b87 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 6 Jul 2023 22:14:12 +0300 Subject: [PATCH 2/4] initial files --- client/CMakeLists.txt | 4 ++ client/gui/Shortcut.h | 1 + client/widgets/CArtifactsOfHeroAltar.cpp | 5 ++ client/widgets/CArtifactsOfHeroAltar.h | 1 + client/widgets/CArtifactsOfHeroBackpack.cpp | 71 ++++++++++++++++++ client/widgets/CArtifactsOfHeroBackpack.h | 35 +++++++++ client/widgets/CArtifactsOfHeroBase.cpp | 19 +++-- client/widgets/CArtifactsOfHeroBase.h | 5 +- client/widgets/CArtifactsOfHeroKingdom.cpp | 5 ++ client/widgets/CArtifactsOfHeroKingdom.h | 1 + client/widgets/CArtifactsOfHeroMain.cpp | 5 ++ client/widgets/CArtifactsOfHeroMain.h | 1 + client/widgets/CWindowWithArtifacts.cpp | 80 +++++++++++++-------- client/widgets/CWindowWithArtifacts.h | 5 +- client/windows/CHeroBackpackWindow.cpp | 23 ++++++ client/windows/CHeroBackpackWindow.h | 22 ++++++ client/windows/CHeroWindow.cpp | 8 +++ client/windows/CHeroWindow.h | 2 + client/windows/CTradeWindow.cpp | 6 +- 19 files changed, 257 insertions(+), 42 deletions(-) create mode 100644 client/widgets/CArtifactsOfHeroBackpack.cpp create mode 100644 client/widgets/CArtifactsOfHeroBackpack.h create mode 100644 client/windows/CHeroBackpackWindow.cpp create mode 100644 client/windows/CHeroBackpackWindow.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e41d22705..3eeae7018 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -105,6 +105,7 @@ set(client_SRCS widgets/CArtifactsOfHeroKingdom.cpp widgets/CArtifactsOfHeroAltar.cpp widgets/CArtifactsOfHeroMarket.cpp + widgets/CArtifactsOfHeroBackpack.cpp widgets/CWindowWithArtifacts.cpp windows/CCastleInterface.cpp @@ -121,6 +122,7 @@ set(client_SRCS windows/GUIClasses.cpp windows/InfoWindows.cpp windows/QuickRecruitmentWindow.cpp + windows/CHeroBackpackWindow.cpp windows/settings/GeneralOptionsTab.cpp windows/settings/OtherOptionsTab.cpp windows/settings/SettingsMainWindow.cpp @@ -258,6 +260,7 @@ set(client_HEADERS widgets/CArtifactsOfHeroKingdom.h widgets/CArtifactsOfHeroAltar.h widgets/CArtifactsOfHeroMarket.h + widgets/CArtifactsOfHeroBackpack.h widgets/CWindowWithArtifacts.h windows/CCastleInterface.h @@ -274,6 +277,7 @@ set(client_HEADERS windows/GUIClasses.h windows/InfoWindows.h windows/QuickRecruitmentWindow.h + windows/CHeroBackpackWindow.h windows/settings/GeneralOptionsTab.h windows/settings/OtherOptionsTab.h windows/settings/SettingsMainWindow.h diff --git a/client/gui/Shortcut.h b/client/gui/Shortcut.h index 778bfaac9..c36b98526 100644 --- a/client/gui/Shortcut.h +++ b/client/gui/Shortcut.h @@ -154,6 +154,7 @@ enum class EShortcut HERO_LOOSE_FORMATION, HERO_TIGHT_FORMATION, HERO_TOGGLE_TACTICS, // b + HERO_BACKPACK, // Spellbook screen SPELLBOOK_TAB_ADVENTURE, diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index 8a7bd01b6..190eb0cbf 100644 --- a/client/widgets/CArtifactsOfHeroAltar.cpp +++ b/client/widgets/CArtifactsOfHeroAltar.cpp @@ -28,6 +28,11 @@ CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) pickedArtFromSlot = ArtifactPosition::PRE_FIRST; }; +CArtifactsOfHeroAltar::~CArtifactsOfHeroAltar() +{ + putBackPickedArtifact(); +} + void CArtifactsOfHeroAltar::setHero(const CGHeroInstance * hero) { if(hero) diff --git a/client/widgets/CArtifactsOfHeroAltar.h b/client/widgets/CArtifactsOfHeroAltar.h index 774376342..83fd2b6f4 100644 --- a/client/widgets/CArtifactsOfHeroAltar.h +++ b/client/widgets/CArtifactsOfHeroAltar.h @@ -21,6 +21,7 @@ public: CArtifactFittingSet visibleArtSet; CArtifactsOfHeroAltar(const Point & position); + ~CArtifactsOfHeroAltar(); void setHero(const CGHeroInstance * hero) override; void updateWornSlots() override; void updateBackpackSlots() override; diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp new file mode 100644 index 000000000..48a8824a4 --- /dev/null +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -0,0 +1,71 @@ +/* + * CArtifactsOfHeroBackpack.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CArtifactsOfHeroBackpack.h" + +#include "../gui/CGuiHandler.h" +#include "../gui/Shortcut.h" + +#include "Buttons.h" +#include "GameSettings.h" +#include "IHandlerBase.h" + +#include "../CPlayerInterface.h" + +#include "../../CCallback.h" + +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position, DestroyHandler destroyThisCallback) +{ + OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); + pos += position; + + const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); + auto visibleCapasityMax = HERO_BACKPACK_WINDOW_SLOT_LINES * HERO_BACKPACK_WINDOW_SLOT_COLUMNS; + if(backpackCap >= 0) + visibleCapasityMax = visibleCapasityMax > backpackCap ? backpackCap : visibleCapasityMax; + + backpack.resize(visibleCapasityMax); + size_t artPlaceIdx = 0; + for(auto & artPlace : backpack) + { + artPlace = std::make_shared( + Point(46 * (artPlaceIdx % HERO_BACKPACK_WINDOW_SLOT_COLUMNS), 46 * (artPlaceIdx / HERO_BACKPACK_WINDOW_SLOT_COLUMNS))); + artPlace->setArtifact(nullptr); + artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1); + artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1); + artPlaceIdx++; + } + if(backpackCap < 0 || visibleCapasityMax < backpackCap) + { + auto scrollHandler = std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1); + leftBackpackRoll = std::make_shared(Point(-20, 0), "hsbtns3.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::MOVE_LEFT); + rightBackpackRoll = std::make_shared(Point(368, 318), "hsbtns5.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::MOVE_RIGHT); + leftBackpackRoll->block(true); + rightBackpackRoll->block(true); + } + this->destroyThisCallback = destroyThisCallback; +} + +void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) +{ + LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); +} + +void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace) +{ + LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot), + ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS)); +} + +void CArtifactsOfHeroBackpack::destroyThis() +{ + if(destroyThisCallback) + destroyThisCallback(); +} diff --git a/client/widgets/CArtifactsOfHeroBackpack.h b/client/widgets/CArtifactsOfHeroBackpack.h new file mode 100644 index 000000000..47131b751 --- /dev/null +++ b/client/widgets/CArtifactsOfHeroBackpack.h @@ -0,0 +1,35 @@ +/* + * CArtifactsOfHeroBackpack.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "CArtifactsOfHeroBase.h" + +VCMI_LIB_NAMESPACE_BEGIN + +struct ArtifactLocation; + +VCMI_LIB_NAMESPACE_END + +class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase +{ +public: + using DestroyHandler = std::function; + + CArtifactsOfHeroBackpack(const Point & position, DestroyHandler destroyThisCallback); + void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); + void pickUpArtifact(CHeroArtPlace & artPlace); + void destroyThis(); + +private: + DestroyHandler destroyThisCallback; + + const size_t HERO_BACKPACK_WINDOW_SLOT_COLUMNS = 8; + const size_t HERO_BACKPACK_WINDOW_SLOT_LINES = 8; +}; \ No newline at end of file diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 38e9371f9..2e629b8b8 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -11,7 +11,6 @@ #include "CArtifactsOfHeroBase.h" #include "../gui/CGuiHandler.h" -#include "../gui/CursorHandler.h" #include "../gui/Shortcut.h" #include "Buttons.h" @@ -26,11 +25,12 @@ CArtifactsOfHeroBase::CArtifactsOfHeroBase() : backpackPos(0), - curHero(nullptr) + curHero(nullptr), + putBackPickedArtCallback(nullptr) { } -CArtifactsOfHeroBase::~CArtifactsOfHeroBase() +void CArtifactsOfHeroBase::putBackPickedArtifact() { // Artifact located in artifactsTransitionPos should be returned if(getPickedArtifact()) @@ -45,6 +45,13 @@ CArtifactsOfHeroBase::~CArtifactsOfHeroBase() LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS), ArtifactLocation(curHero, slot)); } } + if(putBackPickedArtCallback) + putBackPickedArtCallback(); +} + +void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCallback callback) +{ + putBackPickedArtCallback = callback; } void CArtifactsOfHeroBase::init( @@ -159,8 +166,10 @@ void CArtifactsOfHeroBase::scrollBackpackForArtSet(int offset, const CArtifactSe } // Blocking scrolling if there is not enough artifacts to scroll - leftBackpackRoll->block(!scrollingPossible); - rightBackpackRoll->block(!scrollingPossible); + if(leftBackpackRoll) + leftBackpackRoll->block(!scrollingPossible); + if(rightBackpackRoll) + rightBackpackRoll->block(!scrollingPossible); } void CArtifactsOfHeroBase::safeRedraw() diff --git a/client/widgets/CArtifactsOfHeroBase.h b/client/widgets/CArtifactsOfHeroBase.h index 743a98254..f7da73d79 100644 --- a/client/widgets/CArtifactsOfHeroBase.h +++ b/client/widgets/CArtifactsOfHeroBase.h @@ -20,12 +20,14 @@ protected: public: using ArtPlaceMap = std::map; using ClickHandler = std::function; + using PutBackPickedArtCallback = std::function; ClickHandler leftClickCallback; ClickHandler rightClickCallback; CArtifactsOfHeroBase(); - virtual ~CArtifactsOfHeroBase(); + virtual void putBackPickedArtifact(); + virtual void setPutBackPickedArtifactCallback(PutBackPickedArtCallback callback); virtual void leftClickArtPlace(CHeroArtPlace & artPlace); virtual void rightClickArtPlace(CHeroArtPlace & artPlace); virtual void setHero(const CGHeroInstance * hero); @@ -47,6 +49,7 @@ protected: std::shared_ptr leftBackpackRoll; std::shared_ptr rightBackpackRoll; int backpackPos; // Position to display artifacts in heroes backpack + PutBackPickedArtCallback putBackPickedArtCallback; const std::vector slotPos = { diff --git a/client/widgets/CArtifactsOfHeroKingdom.cpp b/client/widgets/CArtifactsOfHeroKingdom.cpp index 3b9d2716d..059f196fa 100644 --- a/client/widgets/CArtifactsOfHeroKingdom.cpp +++ b/client/widgets/CArtifactsOfHeroKingdom.cpp @@ -41,6 +41,11 @@ CArtifactsOfHeroKingdom::CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vecto rightBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, +1)); } +CArtifactsOfHeroKingdom::~CArtifactsOfHeroKingdom() +{ + putBackPickedArtifact(); +} + void CArtifactsOfHeroKingdom::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) { LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); diff --git a/client/widgets/CArtifactsOfHeroKingdom.h b/client/widgets/CArtifactsOfHeroKingdom.h index e79dd4b8d..84f6ad185 100644 --- a/client/widgets/CArtifactsOfHeroKingdom.h +++ b/client/widgets/CArtifactsOfHeroKingdom.h @@ -22,6 +22,7 @@ class CArtifactsOfHeroKingdom : public CArtifactsOfHeroBase public: CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vector Backpack, std::shared_ptr leftScroll, std::shared_ptr rightScroll); + ~CArtifactsOfHeroKingdom(); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickUpArtifact(CHeroArtPlace & artPlace); }; \ No newline at end of file diff --git a/client/widgets/CArtifactsOfHeroMain.cpp b/client/widgets/CArtifactsOfHeroMain.cpp index d4038b360..fd8e78b3a 100644 --- a/client/widgets/CArtifactsOfHeroMain.cpp +++ b/client/widgets/CArtifactsOfHeroMain.cpp @@ -23,6 +23,11 @@ CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position) std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1)); } +CArtifactsOfHeroMain::~CArtifactsOfHeroMain() +{ + putBackPickedArtifact(); +} + void CArtifactsOfHeroMain::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) { LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); diff --git a/client/widgets/CArtifactsOfHeroMain.h b/client/widgets/CArtifactsOfHeroMain.h index bbe57781c..6e7253bbe 100644 --- a/client/widgets/CArtifactsOfHeroMain.h +++ b/client/widgets/CArtifactsOfHeroMain.h @@ -21,6 +21,7 @@ class CArtifactsOfHeroMain : public CArtifactsOfHeroBase { public: CArtifactsOfHeroMain(const Point & position); + ~CArtifactsOfHeroMain(); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickUpArtifact(CHeroArtPlace & artPlace); }; diff --git a/client/widgets/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index 45bcc7e54..840bab28e 100644 --- a/client/widgets/CWindowWithArtifacts.cpp +++ b/client/widgets/CWindowWithArtifacts.cpp @@ -26,19 +26,20 @@ #include "../../lib/CGeneralTextHandler.h" #include "../../lib/mapObjects/CGHeroInstance.h" -CWindowWithArtifacts::~CWindowWithArtifacts() -{ - CCS->curh->dragAndDropCursor(nullptr); -} - void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet) { + CArtifactsOfHeroBase::PutBackPickedArtCallback artPutBackHandler = []() -> void + { + CCS->curh->dragAndDropCursor(nullptr); + }; + artSets.emplace_back(artSet); - std::visit([this](auto artSetWeak) + std::visit([this, artPutBackHandler](auto artSetWeak) { auto artSet = artSetWeak.lock(); artSet->leftClickCallback = std::bind(&CWindowWithArtifacts::leftClickArtPlaceHero, this, _1, _2); artSet->rightClickCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2); + artSet->setPutBackPickedArtifactCallback(artPutBackHandler); }, artSet); } @@ -90,35 +91,37 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst { const auto artSetPtr = artSetWeak.lock(); - // Hero(Main, Exchange) window, Kingdom window, Altar window left click handler + // Hero(Main, Exchange) window, Kingdom window, Altar window, Backpack window left click handler if constexpr( std::is_same_v> || std::is_same_v> || - std::is_same_v>) + std::is_same_v> || + std::is_same_v>) { const auto pickedArtInst = getPickedArtifact(); const auto heroPickedArt = getHeroPickedArtifact(); const auto hero = artSetPtr->getHero(); + auto isTransferAllowed = false; + std::string msg; if(pickedArtInst) { auto srcLoc = ArtifactLocation(heroPickedArt, ArtifactPosition::TRANSITION_POS); auto dstLoc = ArtifactLocation(hero, artPlace.slot); - auto isTransferAllowed = false; if(ArtifactUtils::isSlotBackpack(artPlace.slot)) { if(pickedArtInst->artType->isBig()) { // War machines cannot go to backpack - LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % pickedArtInst->artType->getNameTranslated())); + msg = boost::str(boost::format(CGI->generaltexth->allTexts[153]) % pickedArtInst->artType->getNameTranslated()); } else { if(ArtifactUtils::isBackpackFreeSlots(heroPickedArt)) isTransferAllowed = true; else - LOCPLINT->showInfoDialog(CGI->generaltexth->translate("core.genrltxt.152")); + msg = CGI->generaltexth->translate("core.genrltxt.152"); } } // Check if artifact transfer is possible @@ -137,7 +140,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst else { if(artPlace.getArt()) - { + { if(artSetPtr->getHero()->tempOwner == LOCPLINT->playerID) { if(checkSpecialArts(hero, artPlace)) @@ -148,12 +151,23 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst for(const auto artSlot : ArtifactUtils::unmovableSlots()) if(artPlace.slot == artSlot) { - LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[21]); + msg = CGI->generaltexth->allTexts[21]; break; } } } } + + if constexpr(std::is_same_v>) + { + if(!isTransferAllowed) + artSetPtr->destroyThis(); + } + else + { + if(!msg.empty()) + LOCPLINT->showInfoDialog(msg); + } } // Market window left click handler else if constexpr(std::is_same_v>) @@ -189,10 +203,11 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns { const auto artSetPtr = artSetWeak.lock(); - // Hero(Main, Exchange) window, Kingdom window right click handler + // Hero (Main, Exchange) window, Kingdom window, Backpack window right click handler if constexpr( std::is_same_v> || - std::is_same_v>) + std::is_same_v> || + std::is_same_v>) { if(artPlace.getArt()) { @@ -244,19 +259,19 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const if(artSetPtr) { const auto hero = artSetPtr->getHero(); - if(artSetPtr->isActive()) + if(pickedArtInst) { - if(pickedArtInst) + if(artSetPtr->isActive()) { CCS->curh->dragAndDropCursor("artifact", pickedArtInst->artType->getIconIndex()); if(srcLoc.isHolder(hero) || !std::is_same_v>) artSetPtr->markPossibleSlots(pickedArtInst, hero->tempOwner == LOCPLINT->playerID); } - else - { - artSetPtr->unmarkSlots(); - CCS->curh->dragAndDropCursor(nullptr); - } + } + else + { + artSetPtr->unmarkSlots(); + CCS->curh->dragAndDropCursor(nullptr); } if(withRedraw) { @@ -321,19 +336,21 @@ void CWindowWithArtifacts::updateSlots(const ArtifactPosition & slot) std::optional> CWindowWithArtifacts::getState() { const CArtifactInstance * artInst = nullptr; - const CGHeroInstance * hero = nullptr; - size_t pickedCnt = 0; + std::map pickedCnt; - auto getHeroArtBody = [&hero, &artInst, &pickedCnt](auto artSetWeak) -> void + auto getHeroArtBody = [&artInst, &pickedCnt](auto artSetWeak) -> void { auto artSetPtr = artSetWeak.lock(); if(artSetPtr) { if(const auto art = artSetPtr->getPickedArtifact()) { - artInst = art; - hero = artSetPtr->getHero(); - pickedCnt += hero->artifactsTransitionPos.size(); + const auto hero = artSetPtr->getHero(); + if(pickedCnt.count(hero) == 0) + { + pickedCnt.insert({ hero, hero->artifactsTransitionPos.size() }); + artInst = art; + } } } }; @@ -343,10 +360,13 @@ std::optional> CWind // The state is possible when the hero has placed an artifact in the ArtifactPosition::TRANSITION_POS, // and the previous artifact has not yet removed from the ArtifactPosition::TRANSITION_POS. // This is a transitional state. Then return nullopt. - if(pickedCnt > 1) + if(std::accumulate(std::begin(pickedCnt), std::end(pickedCnt), 0, [](size_t accum, const auto & value) + { + return accum + value.second; + }) > 1) return std::nullopt; else - return std::make_tuple(hero, artInst); + return std::make_tuple(pickedCnt.begin()->first, artInst); } std::optional CWindowWithArtifacts::findAOHbyRef(CArtifactsOfHeroBase & artsInst) diff --git a/client/widgets/CWindowWithArtifacts.h b/client/widgets/CWindowWithArtifacts.h index 51df78be4..8c463d9ac 100644 --- a/client/widgets/CWindowWithArtifacts.h +++ b/client/widgets/CWindowWithArtifacts.h @@ -14,6 +14,7 @@ #include "CArtifactsOfHeroKingdom.h" #include "CArtifactsOfHeroAltar.h" #include "CArtifactsOfHeroMarket.h" +#include "CArtifactsOfHeroBackpack.h" class CWindowWithArtifacts : public CArtifactHolder { @@ -22,9 +23,9 @@ public: std::weak_ptr, std::weak_ptr, std::weak_ptr, - std::weak_ptr>; + std::weak_ptr, + std::weak_ptr>; - virtual ~CWindowWithArtifacts(); void addSet(CArtifactsOfHeroPtr artSet); const CGHeroInstance * getHeroPickedArtifact(); const CArtifactInstance * getPickedArtifact(); diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp new file mode 100644 index 000000000..56b1b6b28 --- /dev/null +++ b/client/windows/CHeroBackpackWindow.cpp @@ -0,0 +1,23 @@ +/* + * CHeroBackpackWindow.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CHeroBackpackWindow.h" + +#include "../gui/CGuiHandler.h" + +CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) + : CWindowObject(PLAYER_COLORED) +{ + OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); + + arts = std::make_shared(Point(-100, -170), std::bind(&CHeroBackpackWindow::close, this)); + arts->setHero(hero); + addSet(arts); +} \ No newline at end of file diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h new file mode 100644 index 000000000..5e9882340 --- /dev/null +++ b/client/windows/CHeroBackpackWindow.h @@ -0,0 +1,22 @@ +/* + * CHeroBackpackWindow.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "../widgets/CWindowWithArtifacts.h" +#include "CWindowObject.h" + +class CHeroBackpackWindow : public CWindowObject, public CWindowWithArtifacts +{ +public: + CHeroBackpackWindow(const CGHeroInstance * hero); + +private: + std::shared_ptr arts; +}; \ No newline at end of file diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 331962d7a..70c5cf678 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -11,6 +11,7 @@ #include "CHeroWindow.h" #include "CCreatureWindow.h" +#include "CHeroBackpackWindow.h" #include "CKingdomInterface.h" #include "GUIClasses.h" @@ -136,6 +137,8 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero) questlogLabel = std::make_shared(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE); questlogButton = std::make_shared(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, EShortcut::ADVENTURE_QUEST_LOG); + backpackButton = std::make_shared(Point(380, 429), "hsbtns2.def", CButton::tooltip(""), [=]() { createBackpackWindow(); }, EShortcut::HERO_BACKPACK); + formations = std::make_shared(0); formations->addToggle(0, std::make_shared(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, EShortcut::HERO_TIGHT_FORMATION)); formations->addToggle(1, std::make_shared(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, EShortcut::HERO_LOOSE_FORMATION)); @@ -357,6 +360,11 @@ void CHeroWindow::dismissCurrent() LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, nullptr); } +void CHeroWindow::createBackpackWindow() +{ + GH.windows().createAndPushWindow(curHero); +} + void CHeroWindow::commanderWindow() { const auto pickedArtInst = getPickedArtifact(); diff --git a/client/windows/CHeroWindow.h b/client/windows/CHeroWindow.h index 487d881b6..a391f2b92 100644 --- a/client/windows/CHeroWindow.h +++ b/client/windows/CHeroWindow.h @@ -105,6 +105,7 @@ class CHeroWindow : public CStatusbarWindow, public CGarrisonHolder, public CWin std::shared_ptr questlogLabel; std::shared_ptr questlogButton; std::shared_ptr commanderButton; + std::shared_ptr backpackButton; std::shared_ptr tacticsButton; std::shared_ptr formations; @@ -125,6 +126,7 @@ public: void commanderWindow(); void switchHero(); //changes displayed hero void updateGarrisons() override; + void createBackpackWindow(); //friends friend void CHeroArtPlace::clickPressed(const Point & cursorPosition); diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index d52f3fbc3..6787308fd 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -370,7 +370,6 @@ void CTradeWindow::initItems(bool Left) if(Left && (itemsType[1] == ARTIFACT_TYPE || itemsType[1] == ARTIFACT_INSTANCE)) { - int xOffset = 0, yOffset = 0; if(mode == EMarketMode::ARTIFACT_RESOURCE) { auto item = std::make_shared(Point(137, 469), itemsType[Left], -1, 1, 0); @@ -1428,10 +1427,9 @@ int CAltarWindow::firstFreeSlot() void CAltarWindow::SacrificeBackpack() { - auto artsAltar = std::dynamic_pointer_cast(arts); - while(!artsAltar->visibleArtSet.artifactsInBackpack.empty()) + while(!arts->visibleArtSet.artifactsInBackpack.empty()) { - if(!putOnAltar(nullptr, artsAltar->visibleArtSet.artifactsInBackpack[0].artifact)) + if(!putOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact)) break; }; calcTotalExp(); From b1351d8532c611294a4216371d08f6724d1e24ba Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 16 Jul 2023 21:16:12 +0300 Subject: [PATCH 3/4] two scrolling modes demo --- client/widgets/CArtifactsOfHeroBackpack.cpp | 36 ++++++++++++++++----- client/widgets/CArtifactsOfHeroBackpack.h | 13 +++----- client/widgets/CArtifactsOfHeroBase.cpp | 2 +- client/widgets/CWindowWithArtifacts.cpp | 10 +++++- client/widgets/CWindowWithArtifacts.h | 3 ++ client/windows/CHeroBackpackWindow.cpp | 11 +++++-- client/windows/CHeroBackpackWindow.h | 3 +- 7 files changed, 57 insertions(+), 21 deletions(-) diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp index 48a8824a4..983a5b57d 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.cpp +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -18,10 +18,11 @@ #include "IHandlerBase.h" #include "../CPlayerInterface.h" +#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../CCallback.h" -CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position, DestroyHandler destroyThisCallback) +CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position) { OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); pos += position; @@ -44,13 +45,12 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position, Destr } if(backpackCap < 0 || visibleCapasityMax < backpackCap) { - auto scrollHandler = std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1); - leftBackpackRoll = std::make_shared(Point(-20, 0), "hsbtns3.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::MOVE_LEFT); - rightBackpackRoll = std::make_shared(Point(368, 318), "hsbtns5.def", CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::MOVE_RIGHT); + auto scrollHandler = std::bind(&CArtifactsOfHeroBackpack::scrollBackpack, this, _1); + leftBackpackRoll = std::make_shared(Point(-20, 0), "hsbtns3.def", CButton::tooltip(), [=]() { scrollHandler(-HERO_BACKPACK_WINDOW_SLOT_COLUMNS); }, EShortcut::MOVE_LEFT); + rightBackpackRoll = std::make_shared(Point(368, 318), "hsbtns5.def", CButton::tooltip(), [=]() { scrollHandler(HERO_BACKPACK_WINDOW_SLOT_COLUMNS); }, EShortcut::MOVE_RIGHT); leftBackpackRoll->block(true); rightBackpackRoll->block(true); } - this->destroyThisCallback = destroyThisCallback; } void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) @@ -64,8 +64,28 @@ void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace) ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS)); } -void CArtifactsOfHeroBackpack::destroyThis() +void CArtifactsOfHeroBackpack::scrollBackpack(int offset) { - if(destroyThisCallback) - destroyThisCallback(); + if(isScrollStraight) + { + // offset==-1 => to up; offset==1 => to down + backpackPos += offset; + auto slot = ArtifactPosition(GameConstants::BACKPACK_START + backpackPos); + for(auto artPlace : backpack) + { + setSlotData(artPlace, slot, *curHero); + slot = slot + 1; + } + + // Blocking scrolling if there is not enough artifacts to scroll + if(leftBackpackRoll) + leftBackpackRoll->block(backpackPos <= 0); + if(rightBackpackRoll) + rightBackpackRoll->block(backpackPos + backpack.size() >= curHero->artifactsInBackpack.size()); + redraw(); + } + else + { + CArtifactsOfHeroBase::scrollBackpack(offset); + } } diff --git a/client/widgets/CArtifactsOfHeroBackpack.h b/client/widgets/CArtifactsOfHeroBackpack.h index 47131b751..bc8c51cc8 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.h +++ b/client/widgets/CArtifactsOfHeroBackpack.h @@ -20,16 +20,13 @@ VCMI_LIB_NAMESPACE_END class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase { public: - using DestroyHandler = std::function; - - CArtifactsOfHeroBackpack(const Point & position, DestroyHandler destroyThisCallback); + CArtifactsOfHeroBackpack(const Point & position); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickUpArtifact(CHeroArtPlace & artPlace); - void destroyThis(); - -private: - DestroyHandler destroyThisCallback; + void scrollBackpack(int offset); + bool isScrollStraight = false; +private: const size_t HERO_BACKPACK_WINDOW_SLOT_COLUMNS = 8; const size_t HERO_BACKPACK_WINDOW_SLOT_LINES = 8; -}; \ No newline at end of file +}; diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 2e629b8b8..cbd108267 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -116,7 +116,7 @@ void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero) { setSlotData(slot.second, slot.first, *curHero); } - scrollBackpackForArtSet(0, *curHero); + scrollBackpack(0); } const CGHeroInstance * CArtifactsOfHeroBase::getHero() const diff --git a/client/widgets/CWindowWithArtifacts.cpp b/client/widgets/CWindowWithArtifacts.cpp index 840bab28e..5bd2a00a3 100644 --- a/client/widgets/CWindowWithArtifacts.cpp +++ b/client/widgets/CWindowWithArtifacts.cpp @@ -43,6 +43,11 @@ void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet) }, artSet); } +void CWindowWithArtifacts::addCloseCallback(CloseCallback callback) +{ + closeCallback = callback; +} + const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact() { auto res = getState(); @@ -161,7 +166,10 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst if constexpr(std::is_same_v>) { if(!isTransferAllowed) - artSetPtr->destroyThis(); + { + if(closeCallback) + closeCallback(); + } } else { diff --git a/client/widgets/CWindowWithArtifacts.h b/client/widgets/CWindowWithArtifacts.h index 8c463d9ac..c5180c688 100644 --- a/client/widgets/CWindowWithArtifacts.h +++ b/client/widgets/CWindowWithArtifacts.h @@ -25,8 +25,10 @@ public: std::weak_ptr, std::weak_ptr, std::weak_ptr>; + using CloseCallback = std::function; void addSet(CArtifactsOfHeroPtr artSet); + void addCloseCallback(CloseCallback callback); const CGHeroInstance * getHeroPickedArtifact(); const CArtifactInstance * getPickedArtifact(); void leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst, CHeroArtPlace & artPlace); @@ -39,6 +41,7 @@ public: private: std::vector artSets; + CloseCallback closeCallback; void updateSlots(const ArtifactPosition & slot); std::optional> getState(); diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp index 56b1b6b28..e99ee2b41 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -17,7 +17,14 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) { OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); - arts = std::make_shared(Point(-100, -170), std::bind(&CHeroBackpackWindow::close, this)); + arts = std::make_shared(Point(-100, -170)); arts->setHero(hero); addSet(arts); -} \ No newline at end of file + + arts_straight = std::make_shared(Point(-500, -170)); + arts_straight->setHero(hero); + arts_straight->isScrollStraight = true; + addSet(arts_straight); + + addCloseCallback(std::bind(&CHeroBackpackWindow::close, this)); +} diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h index 5e9882340..42208622a 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -19,4 +19,5 @@ public: private: std::shared_ptr arts; -}; \ No newline at end of file + std::shared_ptr arts_straight; +}; From ca977d7105e1f8fdbfef0de27abfc94e6b8058be Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 17 Jul 2023 19:42:55 +0300 Subject: [PATCH 4/4] backpack window slider --- client/widgets/CArtifactsOfHeroBackpack.cpp | 58 ++++++++++++--------- client/widgets/CArtifactsOfHeroBackpack.h | 8 ++- client/widgets/CArtifactsOfHeroBase.cpp | 2 +- client/widgets/ObjectLists.cpp | 35 +++++++++++++ client/widgets/ObjectLists.h | 24 +++++++-- client/windows/CHeroBackpackWindow.cpp | 10 ++-- client/windows/CHeroBackpackWindow.h | 2 +- client/windows/CHeroWindow.cpp | 2 - 8 files changed, 101 insertions(+), 40 deletions(-) diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp index 983a5b57d..18a704a19 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.cpp +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -16,6 +16,7 @@ #include "Buttons.h" #include "GameSettings.h" #include "IHandlerBase.h" +#include "ObjectLists.h" #include "../CPlayerInterface.h" #include "../../lib/mapObjects/CGHeroInstance.h" @@ -43,13 +44,20 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position) artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1); artPlaceIdx++; } + if(backpackCap < 0 || visibleCapasityMax < backpackCap) { - auto scrollHandler = std::bind(&CArtifactsOfHeroBackpack::scrollBackpack, this, _1); - leftBackpackRoll = std::make_shared(Point(-20, 0), "hsbtns3.def", CButton::tooltip(), [=]() { scrollHandler(-HERO_BACKPACK_WINDOW_SLOT_COLUMNS); }, EShortcut::MOVE_LEFT); - rightBackpackRoll = std::make_shared(Point(368, 318), "hsbtns5.def", CButton::tooltip(), [=]() { scrollHandler(HERO_BACKPACK_WINDOW_SLOT_COLUMNS); }, EShortcut::MOVE_RIGHT); - leftBackpackRoll->block(true); - rightBackpackRoll->block(true); + 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_LINES, 0, 0, 1, + Rect(HERO_BACKPACK_WINDOW_SLOT_COLUMNS * 46 + 10, 0, HERO_BACKPACK_WINDOW_SLOT_LINES * 46 - 5, 0)); } } @@ -66,26 +74,26 @@ void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace) void CArtifactsOfHeroBackpack::scrollBackpack(int offset) { - if(isScrollStraight) + if(backpackListBox) + backpackListBox->resize(getActiveSlotLinesNum()); + backpackPos += offset; + auto slot = ArtifactPosition(GameConstants::BACKPACK_START + backpackPos); + for(auto artPlace : backpack) { - // offset==-1 => to up; offset==1 => to down - backpackPos += offset; - auto slot = ArtifactPosition(GameConstants::BACKPACK_START + backpackPos); - for(auto artPlace : backpack) - { - setSlotData(artPlace, slot, *curHero); - slot = slot + 1; - } - - // Blocking scrolling if there is not enough artifacts to scroll - if(leftBackpackRoll) - leftBackpackRoll->block(backpackPos <= 0); - if(rightBackpackRoll) - rightBackpackRoll->block(backpackPos + backpack.size() >= curHero->artifactsInBackpack.size()); - redraw(); - } - else - { - CArtifactsOfHeroBase::scrollBackpack(offset); + setSlotData(artPlace, slot, *curHero); + slot = slot + 1; } + redraw(); +} + +void CArtifactsOfHeroBackpack::updateBackpackSlots() +{ + if(backpackListBox) + backpackListBox->resize(getActiveSlotLinesNum()); + CArtifactsOfHeroBase::updateBackpackSlots(); +} + +size_t CArtifactsOfHeroBackpack::getActiveSlotLinesNum() +{ + return (curHero->artifactsInBackpack.size() + HERO_BACKPACK_WINDOW_SLOT_COLUMNS - 1) / HERO_BACKPACK_WINDOW_SLOT_COLUMNS; } diff --git a/client/widgets/CArtifactsOfHeroBackpack.h b/client/widgets/CArtifactsOfHeroBackpack.h index bc8c51cc8..f504ba62c 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.h +++ b/client/widgets/CArtifactsOfHeroBackpack.h @@ -17,16 +17,20 @@ struct ArtifactLocation; VCMI_LIB_NAMESPACE_END +class CListBoxWithCallback; + class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase { public: CArtifactsOfHeroBackpack(const Point & position); void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); void pickUpArtifact(CHeroArtPlace & artPlace); - void scrollBackpack(int offset); + void scrollBackpack(int offset) override; + void updateBackpackSlots() override; + size_t getActiveSlotLinesNum(); - bool isScrollStraight = false; private: + std::shared_ptr backpackListBox; const size_t HERO_BACKPACK_WINDOW_SLOT_COLUMNS = 8; const size_t HERO_BACKPACK_WINDOW_SLOT_LINES = 8; }; diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index cbd108267..799135837 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -232,7 +232,7 @@ void CArtifactsOfHeroBase::updateBackpackSlots() { if(curHero->artifactsInBackpack.size() <= backpack.size() && backpackPos != 0) backpackPos = 0; - scrollBackpackForArtSet(0, *curHero); + scrollBackpack(0); } void CArtifactsOfHeroBase::updateSlot(const ArtifactPosition & slot) diff --git a/client/widgets/ObjectLists.cpp b/client/widgets/ObjectLists.cpp index 421be9d35..e86b473e5 100644 --- a/client/widgets/ObjectLists.cpp +++ b/client/widgets/ObjectLists.cpp @@ -245,3 +245,38 @@ const std::list> & CListBox::getItems() { return items; } + +CListBoxWithCallback::CListBoxWithCallback(CListBoxWithCallback::MovedPosCallback callback, CreateFunc create, Point pos, Point itemOffset, + size_t visibleSize, size_t totalSize, size_t initialPos, int slider, Rect sliderPos) + : CListBox(create, pos, itemOffset, visibleSize, totalSize, initialPos, slider, sliderPos) +{ + movedPosCallback = callback; +} + +void CListBoxWithCallback::scrollTo(size_t pos) +{ + CListBox::scrollTo(pos); + if(movedPosCallback) + movedPosCallback(getPos()); +} + +void CListBoxWithCallback::moveToPos(size_t pos) +{ + CListBox::moveToPos(pos); + if(movedPosCallback) + movedPosCallback(getPos()); +} + +void CListBoxWithCallback::moveToNext() +{ + CListBox::moveToNext(); + if(movedPosCallback) + movedPosCallback(getPos()); +} + +void CListBoxWithCallback::moveToPrev() +{ + CListBox::moveToPrev(); + if(movedPosCallback) + movedPosCallback(getPos()); +} \ No newline at end of file diff --git a/client/widgets/ObjectLists.h b/client/widgets/ObjectLists.h index 8d179e46a..07b81c1be 100644 --- a/client/widgets/ObjectLists.h +++ b/client/widgets/ObjectLists.h @@ -99,12 +99,28 @@ public: size_t getIndexOf(std::shared_ptr item); //scroll list to make item which visible - void scrollTo(size_t which); + virtual void scrollTo(size_t which); //scroll list to specified position - void moveToPos(size_t which); - void moveToNext(); - void moveToPrev(); + virtual void moveToPos(size_t which); + virtual void moveToNext(); + virtual void moveToPrev(); size_t getPos(); }; + +class CListBoxWithCallback : public CListBox +{ +public: + using MovedPosCallback = std::function; + + CListBoxWithCallback(MovedPosCallback callback, CreateFunc create, Point pos, Point itemOffset, size_t visibleSize, + size_t totalSize, size_t initialPos = 0, int slider = 0, Rect sliderPos = Rect()); + void scrollTo(size_t pos) override; + void moveToPos(size_t pos) override; + void moveToNext() override; + void moveToPrev() override; + +private: + MovedPosCallback movedPosCallback; +}; diff --git a/client/windows/CHeroBackpackWindow.cpp b/client/windows/CHeroBackpackWindow.cpp index e99ee2b41..b491bf57d 100644 --- a/client/windows/CHeroBackpackWindow.cpp +++ b/client/windows/CHeroBackpackWindow.cpp @@ -11,6 +11,9 @@ #include "CHeroBackpackWindow.h" #include "../gui/CGuiHandler.h" +#include "../gui/Shortcut.h" + +#include "../widgets/Buttons.h" CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) : CWindowObject(PLAYER_COLORED) @@ -21,10 +24,7 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero) arts->setHero(hero); addSet(arts); - arts_straight = std::make_shared(Point(-500, -170)); - arts_straight->setHero(hero); - arts_straight->isScrollStraight = true; - addSet(arts_straight); - addCloseCallback(std::bind(&CHeroBackpackWindow::close, this)); + + quitButton = std::make_shared(Point(242, 200), "hsbtns.def", CButton::tooltip(""), [this]() { close(); }, EShortcut::GLOBAL_RETURN); } diff --git a/client/windows/CHeroBackpackWindow.h b/client/windows/CHeroBackpackWindow.h index 42208622a..fefd1902d 100644 --- a/client/windows/CHeroBackpackWindow.h +++ b/client/windows/CHeroBackpackWindow.h @@ -19,5 +19,5 @@ public: private: std::shared_ptr arts; - std::shared_ptr arts_straight; + std::shared_ptr quitButton; }; diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 70c5cf678..eacbd6ff8 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -137,8 +137,6 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero) questlogLabel = std::make_shared(CGI->generaltexth->jktexts[9], Rect(510, 430, 65, 35), 0, FONT_SMALL, ETextAlignment::TOPLEFT, Colors::WHITE); questlogButton = std::make_shared(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, EShortcut::ADVENTURE_QUEST_LOG); - backpackButton = std::make_shared(Point(380, 429), "hsbtns2.def", CButton::tooltip(""), [=]() { createBackpackWindow(); }, EShortcut::HERO_BACKPACK); - formations = std::make_shared(0); formations->addToggle(0, std::make_shared(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, EShortcut::HERO_TIGHT_FORMATION)); formations->addToggle(1, std::make_shared(Point(481, 519), "hsbtns7.def", std::make_pair(heroscrn[24], heroscrn[30]), 0, EShortcut::HERO_LOOSE_FORMATION));